向量到c ++中的数组和数组大小

时间:2017-01-04 15:20:07

标签: c++ arrays vector

我有一个结构:

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

并初始化struct xyz类型向量:

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()太大了。 所以我想知道有没有办法将这个大尺寸的矢量转换为数组而没有这个问题。 我感谢任何帮助

1 个答案:

答案 0 :(得分:0)

我过于迂腐的评论太大了,所以相反我会试着让这个答案变得有点迂回。简短的回答可能只是坚持使用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,你应该从堆中分配。

一个vector和一个数组将在内存布局方面完全相同;它们的不同之处在于vector从堆中分配内存,而数组(当你编写它时)将在堆栈中。我提出的唯一建议是在进入循环之前致电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成员更改为具有默认值),则效率会降低。

说了这么多,你真的应该做基准测试。但是,你应该对最终使用这个数组的代码进行基准测试,而不是构建它的代码;如果建筑占主导地位,我还有其他问题。