向量到数组以及c++中的数组大小

vector to array and array size in c++

本文关键字:数组 向量 c++      更新时间:2023-10-16

我有一个结构:

struct xyz{
int x,y,z;
};

并且我初始化CCD_ 1型矢量:

for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
for (int k = 0; k < N; k++)
{
v.x=i;
v.y=j;
v.z=k;
vect.push_back(v);
}
}
}

然后我想把矢量转换成数组,因为数组比矢量操作快2倍,所以我做

xyz arr[vect.size()];
std::copy(vect.begin(), vect.end(), arr);

当我运行这个程序时,它显示了分段错误,我认为这是因为vect.size()太大。所以我想知道有没有任何方法可以将大尺寸的向量转换为数组而不会出现这个问题。我感谢的任何帮助

我过于迂腐的评论太大了,所以我会尽量让它成为一个有点迂回的答案。简短的答案可能只是坚持使用vector,但要确保使用reserve;哦,还有基准。

你没有说你使用的是什么编译器或C++版本,所以我只使用我当前的gcc.godbolt.org默认值gcc 4.9.2,C++14。我还假设您真的希望它是一个一维数组,而不是更自然的(对于您的示例)3。

如果你在编译时知道N,你可以这样做(假设我得到了正确的数组偏移量计算):

#include <array>
...
std::array<xyz, N*N*N> xyzs;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) {
xyzs[i*N*N+j*N+k] = {i, j, k};
}
}
}

最大的缺点,IMO:

  • 易于出错的偏移量计算
  • 根据N、代码运行的位置等,这可能会破坏堆栈

在我尝试过的编译器上,优化器似乎明白我们正在按连续顺序遍历数组,生成的机器代码更明智,但如果你愿意,也可以这样写:

#include <array>
...
std::array<xyz, N*N*N> xyzs;
auto p = xyzs.data();
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
for (int k = 0; k < N; ++k) {
(*p++) = {i, j, k};
}
}
}

当然,如果您在编译时确实知道N,并且它不会破坏堆栈,那么您可能会考虑一个三维数组xyz xyzs[N][N][N];,因为对于这些东西的最终使用方式来说,这可能更自然。

正如评论中所指出的,可变长度数组不是合法的C++,但它们在C99中是合法的;如果您在编译时不知道N,那么应该在堆外进行分配。

CCD_ 10和阵列最终在存储器布局方面是相同的;它们的不同之处在于struct xyz1从堆中分配内存,而数组(在编写时)将在堆栈上。我唯一的建议是在进入您的循环之前致电reserve

vect.reserve(N*N*N);

这意味着您将只提前进行单个内存分配,而不是从默认构造的vector中获得的增长和复制机制。

假设xyz和您在这里声明的一样简单,您也可以执行类似上面第二个示例的操作:

std::vector<xyz> xyzs{N*N*N};
auto p = xyzs.data();
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
for (int k = 0; k < N; ++k) {
(*p++) = {i, j, k};
}
}
}

您失去了push_back的安全性,如果xyz默认构造函数需要执行任何操作(例如xyz成员被更改为具有默认值),则效率会降低。

说了这么多,你真的应该进行基准测试。但是,您可能应该对最终使用此数组的代码进行基准测试,而不是对构建它的代码进行标准测试;如果建筑在使用中占主导地位,我会有其他顾虑。