假设我写
std::vector<T> littleVector(1);
std::vector<T> bigVector;
bigVector.reserve(100);
bigVector = littleVector;
标准是否规定 bigVector
仍将保留 100 个元素?或者如果我要 push_back
99 个元素,我会经历内存重新分配吗?也许它甚至因 STL 实现而异。
这是之前讨论过的 here但没有给出标准引用。
最佳答案
不幸的是,该标准没有详细说明分配器感知序列容器分配的行为,严格来说确实是不一致的。
我们知道(从表 28 和 23.2.1p7)如果 allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value
是 true
然后分配器在复制分配时被替换。此外,从表 96 和 99 中我们发现,复制分配的复杂性是线性,而操作a = t
的后置条件是a == t
,即(表 96)distance(a.begin(), a.end()) == distance(t.begin(), t.end()) && equal(a.begin(), a.end(), t.begin())
.从 23.2.1p7 开始,复制分配后,如果分配器传播,则 a.get_allocator() == t.get_allocator()
.
关于 vector 容量,23.3.6.3 [vector.capacity]有:
5 - Remarks: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to
reserve()
until the time when an insertion would make the size of the vector greater than the value ofcapacity()
.
如果我们采取library DR341作为阅读标准的指南:
However, the wording of 23.3.6.3 [vector.capacity]paragraph 5 prevents the capacity of a vector being reduced, following a call to reserve(). This invalidates the idiom, as swap() is thus prevented from reducing the capacity. [...]
通过在 23.3.6.3 中添加段落解决了 DR341:
void swap(vector<T,Allocator>& x);
7 - Effects: Exchanges the contents andcapacity()
of*this
with that ofx
.
8 - Complexity: Constant time.
结论是,从图书馆委员会的角度来看,运营只修改capacity()
如果在 23.3.6.3 下提及。 23.3.6.3 下没有提到复制分配,因此不会修改 capacity()
. (移动分配也有同样的问题,特别是考虑到提议的解决方案 Library DR2321。)
显然,这是标准中的一个缺陷,因为复制分配传播不平等的分配器必须导致重新分配,这与 23.3.6.3p5 相矛盾。
我们可以期待并希望通过以下方式解决这个缺陷:
- 非还原
capacity()
关于非分配器修改复制分配; - 未指定
capacity()
关于分配器修改拷贝分配; - 非还原
capacity()
关于非分配器传播的移动分配; - 源容器
capacity()
关于分配器传播的移动分配。
但是,在当前情况下,直到澄清这一点,您最好不要依赖任何特定行为。幸运的是,有一个简单的解决方法可以保证不会减少 capacity()
:
bigVector.assign(littleVector.begin(), littleVector.end());
关于c++ - vector 分配是否会使 `reserve` 无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24260717/