我刚刚发现 std::vector<T>::resize
即使调整到比当前大小高出一个元素的大小,它的容量也会“翻倍”:
std::vector<int> v(50);
v.resize(51);
std::cout << v.capacity() << std::endl;
该程序在 GCC 和 Clang 中输出 100,在 Visual C++ 中输出 75。但是,当我从 resize
切换时至reserve
:
std::vector<int> v(50);
v.reserve(51);
std::cout << v.capacity() << std::endl;
三个编译器的输出都是 51。
我想知道为什么实现对 resize
使用不同的扩展策略和 reserve
.这似乎不一致,我希望这里有同样的行为。
我只是为我的问题添加一个链接,其中报告了对性能的影响: Why are C++ STL vectors 1000x slower when doing many reserves?
添加来自 C++11 标准的引用以阐明 reserve
的要求; §23.3.6.3(2):
After
reserve()
,capacity()
is greater or equal to the argument ofreserve
if reallocation happens...
一些额外的想法:来自 C++11 标准:
Complexity: The complexity is linear in the number of elements inserted plus the distance to the end of the vector.
这实际上意味着在末尾插入单个元素的恒定(摊销)复杂性。但是,这仅适用于 vector 修饰符,例如 push_back
或 insert
(§23.3.6.5)。
resize
未在修饰符中列出。它列在 §23.3.6.3 vector
容量部分。而且,resize
没有复杂性要求.
但是,在 vector
概述部分(§23.3.6.1),写着:
it (
vector
) supports (amortized) constant time insert and erase operations at the end
问题是resize(size()+1)
被认为是“最后插入”。
最佳答案
据我所知,resize
和 reserve
都不需要具有演示的行为。然而,两者都被允许这样的行为,尽管两者都可以分配确切的数量,并且就标准而言,两者都可以乘以先前的分配。
每种分配策略都有其优势。分配精确数量的优点是,当预先知道最大分配时,它没有内存开销。乘法的优点是它在与末端插入操作混合时保持不变的摊销属性。
测试实现选择的方法的优点是在调整大小时允许两种策略。要使用一种策略,可以保留然后调整大小。要使用另一个,只需调整大小。当然,必须意识到未指定的行为才能利用这一点。这种优势可能是也可能不是选择这些实现的原因。
人们可能会认为这是标准中规定的 vector API 的失败,即无法表达预期的重新分配行为(以标准保证的方式)。
关于c++ - 为什么 std::vector 不保留 "double"它的容量,而调整大小呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48537812/