如何在不增加向量大小的情况下保留多维向量?

How to reserve a multi-dimensional Vector without increasing the vector size?

我有 N 乘 4 的数据,我按如下方式返回数据。

vector<vector<int>> a;
for(some loop){
   ...
   a.push_back(vector<int>(4){val1,val2,val3,val4});
}

N会小于13000,为了防止不必要的重新分配,我想提前4个位预留13000。

在阅读了有关此主题的多篇相关帖子后(例如 How to reserve a multi-dimensional Vector?),我知道以下内容可以解决问题。但我想用 reserve() 或任何类似的函数来实现,以便能够使用 push_back().

vector<vector<int>> a(13000,vector<int>(4);

vector<vector<int>> a;
a.resize(13000,vector<int>(4));

如何在不增加向量大小的情况下只保留内存?

您已经回答了自己的问题。 有一个函数 vector::reserve 可以完全满足您的需求。

vector<vector<int>> a;
a.reserve(N);
for(some loop){
   ...
   a.push_back(vector<int>(4){val1,val2,val3,val4});
}

这将保留内存以适应 Nvector<int>。请注意,此时内部 vector<int> 的实际大小无关紧要,因为 vector 的数据分配在其他地方,只有指针和一些簿记存储在实际 std::vector-class.

如果您的数据保证为 N x 4,您不会想要使用 std::vector<std::vector<int>>,而是 std::vector<std::array<int, 4>>

为什么?

  • 它是语义上更准确的类型 - std::array 专为固定宽度的连续数据序列而设计。 (它还打开了编译器进行更多性能优化的潜力,尽管这取决于您正在编写的内容。)
  • 您的数据将在内存中连续布局,而不是每个不同的向量分配可能不同的堆位置。

话虽如此 - @pasbi 的回答是正确的:如果最终插入的数量比计划少很多,则可以使用 std::vector::reserve() to allocate space for your outer vector before inserting any actual elements (both for vectors-of-vectors and for vectors-of-arrays). Also, later on, you can use the std::vector::shrink_to_fit() 方法。

最后,另一种选择是使用 and pre-allocate memory for it (GSL is the C++ Core Guidelines Support Library)。

注意:此答案仅供参考,以防万一您遇到大小未知的类似问题;在你的情况下保留 std::vector<std::array<int, 4>> 就可以了。

根据 einpoklum 的回答,如果您没有早点找到它,嵌套 std::vectors 几乎总是一个坏主意,因为他谈到了内存布局。每个内部向量将分配自己的数据块,这些数据块(不一定)与其他向量相邻,这将产生缓存未命中。

最好是:

  • 如前所述,如果每个向量的元素数量固定且已知,请使用 std::array;
  • 或者通过单个 std::vector<T> 大小 N x M 来扁平化您的数据结构。
// Assuming N = 13000, M = 4

std::vector<int> vec;
vec.reserve(13000 * 4);

然后就可以这样访问了:

// Before:
int& element = vec[nIndex][mIndex];

// After:
int& element = vec[mIndex * 13000 + nIndex]; // Still assuming N = 13000