unb*_*d37 3 c++ arrays algorithm stdvector c++17
我有以下一段代码,用于将二维数组转换为一维向量。数组使用 std::vector 分配,嵌套的 for_each 循环用于将二维数组的内容传输到一维数组。
#include <iostream>
#include <algorithm>
#include <vector>
#include <stdexcept>
#define UNUSED(expr) (void)(expr)
using usll = __uint64_t;
void print1d(std::vector<double> vv);
void matToVect1d(const std::vector<std::vector<double>>& v2d, std::vector<double>& v1d);
void matToVect1dEx(const std::vector<std::vector<double>>& v2d, std::vector<double>& v1d);
int main(int argc, char* argv[])
{
UNUSED(argc);
UNUSED(argv);
std::cout << std::endl;
const usll DIM0 {10};
const usll DIM1 {8};
std::vector<std::vector<double>> data2d(DIM0, std::vector<double>(DIM1));
std::vector<double> data1d(DIM0 * DIM1);
double temp = 0.0;
for (usll i{}; i<DIM0; ++i)
{
for (usll j{}; j<DIM1; ++j)
{
data2d[i][j] = temp++;
}
}
try
{
matToVect1d(data2d, data1d);
std::cout << "2D array data2d as a 1D vector is:" << std::endl;
print1d(data1d);
std::cout << std::endl;
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}
std::cout << "Press enter to continue";
std::cin.get();
return 0;
}
void print1d(std::vector<double> vv)
{
for (size_t i{}; i<vv.size(); ++i)
{
std::cout << vv[i] << " ";
if ((i+1)%10 == 0)
{
std::cout << std::endl;
}
}
std::cout << std::endl;
}
void matToVect1d(const std::vector<std::vector<double>>& v2d, std::vector<double>& v1d)
{
if (v1d.size() != v2d.size()*v2d[0].size())
{
throw std::runtime_error("An exception was caught. The sizes of the input arrays must match.");
}
for_each(v2d.cbegin(), v2d.cend(), [&v1d](const std::vector<double> vec)
{
for_each(vec.cbegin(), vec.cend(), [&v1d](const double& dValue)
{
v1d.emplace_back(dValue);
});
});
}
void matToVect1dEx(const std::vector<std::vector<double>>& v2d, std::vector<double>& v1d)
{
usll index{};
if (v1d.size() != v2d.size()*v2d[0].size())
{
throw std::runtime_error("An exception was caught. The sizes of the input arrays must match.");
}
for (usll i=0; i<v2d.size(); ++i)
{
for (usll j=0; j<v2d[0].size(); ++j)
{
index = j + i*v2d[0].size();
v1d[index] = v2d[i][j];
}
}
}
Run Code Online (Sandbox Code Playgroud)
每次运行代码时,输出都是:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
Run Code Online (Sandbox Code Playgroud)
这是原始一维数组的两倍。什么?零从哪里来?是什么导致向量大小从 80 增长到 160?相反,当我将 for_each 循环更改为常规 for 循环时,我得到了正确的输出:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
Run Code Online (Sandbox Code Playgroud)
我怀疑异常是由于使用了 for_each 算法,但 Meyer (2018) 在他的书Effective C++ Digital Collection: 140 Ways to Improvement Your Programming 中说“算法调用更可取”。他说,我引用:“从效率的角度来看,算法可以通过三种方式击败显式循环,两种主要方式,一种次要方式。次要方式涉及消除冗余计算。”
在我的实际用例中,该方法matToVect1d()被调用了1000几次,每个数组的元素总数为240 x 200.
我的最后一个问题是使用 for_each 算法实现循环是否有意义?答案将不胜感激。
这是因为线
std::vector<double> data1d(DIM0 * DIM1);
Run Code Online (Sandbox Code Playgroud)
在那里data1d你创建一个s的向量double并用0.0s 在DIM0xDIM0的大小初始化它。因此,以后std::for_each以防万一,当您std::vector::emplace_back在此之后插入元素。因此,您会看到DIM0xDIM0 0和您插入的元素。
您需要std::vector::reserve的是所需的行为
std::vector<double> data1d;
data1d.reserve(DIM0 * DIM1); // for unwated reallocations
Run Code Online (Sandbox Code Playgroud)
我怀疑异常是由于使用了 for_each 算法[...]
不,由于上述原因(即错误)。
我的最后一个问题是使用
std::for_each算法实现循环是否有意义?
方法没有任何问题std::for_each,除了您复制std::vector<double>第一个 lambdas 参数列表中的 并且(可能)可读性较低。
std::for_each(v2d.cbegin(), v2d.cend(), [&v1d](std::vector<double> const& vec)
// ^^^^^^ --> prefer const-ref
{
for_each(vec.cbegin(), vec.cend(), [&v1d](const double dValue)
{
v1d.emplace_back(dValue);
});
});
Run Code Online (Sandbox Code Playgroud)
比范围 -for-loop方法如下所示
std::vector<double> data1d;
data1d.reserve(DIM0 * DIM1); // for unwated reallocations
// ... later in the function
for (const std::vector<double>& vector : v2d)
for (const double element : vector)
v1d.emplace_back(element);
Run Code Online (Sandbox Code Playgroud)
std::vector<double> data1d(DIM0 * DIM1);<- 这行代码不“保留”。它用DIM0 * DIM1默认的初始化双精度填充向量。这是您正在使用的构造函数。
vector( size_type count, const T& value, const Allocator& alloc = Allocator());
检查更多参考:https : //en.cppreference.com/w/cpp/container/vector/vector
改成这样:
std::vector<double> data1d();
data1d.reserve(DIM0 * DIM1);
Run Code Online (Sandbox Code Playgroud)