如何在不增加向量大小的情况下保留多维向量?
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});
}
这将保留内存以适应 N
次 vector<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
我有 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});
}
这将保留内存以适应 N
次 vector<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()
方法。
最后,另一种选择是使用
注意:此答案仅供参考,以防万一您遇到大小未知的类似问题;在你的情况下保留 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