简体   繁体   English

什么时候std :: vector重新分配它的内存数组?

[英]When does a std::vector reallocate its memory array?

I can't find anything that gives a definitive answer. 我找不到任何可以给出明确答案的东西。 I was just curious if a std::vector reallocate its internal array only when it absolutely must or will it reallocate ahead of time in anticipation (so to speak). 我很好奇,如果std :: vector只在绝对必须时重新分配其内部数组,或者它会在预期中提前重新分配(可以这么说)。

For example: 例如:

std::vector<int> myVector;
for (int i = 0; i < 1000; ++i) myVector.push_back(i);

cout << myVector.size() << '\n'      // Gives 1000 as expected
     << myVector.capacity() << endl; // Gives 1024 which makes sense

If I continue to add elements, is there ever any chance that one of the next 24 items I add will change the capacity or will it only reallocate once I put in a 25th item? 如果我继续添加元素,是否有可能我添加的下24个项目中的一个会改变容量,或者只有在我放入第25个项目后它才会重新分配?

Note: 注意:

I did run a test using gcc 4.4.3 under Linux, but and it seems like the reallocation is done "on-demand", but I was curious if I was just lucky or if there is something somewhere stating that this is expected behavior. 我在Linux下使用gcc 4.4.3进行了测试,但似乎重新分配是“按需”完成的,但我很好奇我是不是很幸运,或者有什么东西说明这是预期的行为。

From C++ standard 23.2.4.2: 从C ++标准23.2.4.2开始:

size_type capacity() const;

Returns: The total number of elements that the vector can hold without requiring reallocation. 返回:向量可以容纳的元素总数,无需重新分配。

Also from Standard 也来自标准

Notes: 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 size specified in the most recent call to reserve(). 保证在调用reserve()之后发生的插入期间不会发生重新分配 ,直到插入使向量的大小大于最近调用reserve()时指定的大小为止。

So yes, you can be sure. 所以,是的,你可以肯定。

Edit: As @Bo Persson mentioned there is a catch. 编辑:正如@Bo Persson所说,有一个问题。 Standard doesn't say anything if we never call reserve() . 如果我们从不调用reserve()标准也没有说什么。 However in practice it works well, because no implementation will care to remember if you called reserve, or not. 但是在实践中它运行良好,因为如果你调用reserve,没有实现会记住。 I believe that this is bug. 我相信这是错误。 And as @Martin mentioned in his answer in C++0x draft it is corrected. 正如@Martin在C ++ 0x草案中的回答中提到的那样,它得到了纠正。

From the standard: n3092: Draft C++0x 从标准:n3092:草案C ++ 0x

23.3.6.2 vector capacity [vector capacity] 23.3.6.2载体容量[载体容量]

void reserve(size_type n); void reserve(size_type n);
2 Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. 2效果:一种指令,通知向量计划的大小更改,以便它可以相应地管理存储分配。 After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; 在reserve()之后,如果重新分配,capacity()大于或等于reserve的参数; and equal to the previous value of capacity() otherwise. 并且等于capacity()的先前值。 Reallocation happens at this point if and only if the current capacity is less than the argument of reserve() . 当且仅当当前容量小于reserve()的参数时,才会发生重新分配 If an exception is thrown other than by the move constructor of a non-CopyConstructible type, there are no effects. 如果除了非CopyConstructible类型的移动构造函数之外抛出异常,则没有效果。

23.3.6.4 vector modifiers [vector.modifiers] 23.3.6.4向量修饰符[vector.modifiers]
Remarks: Causes reallocation if the new size is greater than the old capacity . 备注: 如果新大小大于旧容量,则会导致重新分配 If no reallocation happens, all the iterators and references before the insertion point remain valid. 如果没有重新分配,插入点之前的所有迭代器和引用仍然有效。 If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T or by any InputIterator operation there are no effects. 如果除了复制构造函数之外抛出异常,移动构造函数,赋值运算符或T的移动赋值运算符,或者通过任何InputIterator操作都没有效果。 If an exception is thrown by the move constructor of a non-CopyConstructible T, the effects are unspecified. 如果非CopyConstructible T的移动构造函数抛出异常,则不指定效果。

If you look at the documentation for push_back on cplusplus.com it states: 如果你看一下cplusplus.com上的 push_back文档,它说:

This effectively increases the vector size by one, which causes a reallocation of the internal allocated storage if the vector size was equal to the vector capacity before the call. 这有效地将向量大小增加1,如果向量大小等于调用之前的向量容量,则导致内部分配存储的重新分配。 Reallocations invalidate all previously obtained iterators, references and pointers. 重新分配使以前获得的所有迭代器,引用和指针无效。

So I very much doubt the size would change before that but you could always test it. 所以我非常怀疑在此之前尺寸会发生变化,但你可以随时测试它。 At least on my platform the size changes as stated above: 至少在我的平台上,尺寸如上所述变化:

size vs capacity
1020 vs 1024
1021 vs 1024
1022 vs 1024
1023 vs 1024
1024 vs 1024
1025 vs 2048

From cplusplus.com : 来自cplusplus.com

But vectors, also have a capacity, which determines the amount of storage space they have allocated, and which can be either equal or greater than the actual size. 但是矢量也有容量,它决定了它们分配的存储空间量,并且可以等于或大于实际大小。 The extra amount of storage allocated is not used, but is reserved for the vector to be used in the case it grows. 不使用分配的额外存储量,但保留用于在其增长的情况下使用的向量。 This way, the vector does not have to reallocate storage on each occasion it grows, but only when this extra space is exhausted and a new element is inserted (which should only happen in logarithmic frequence in relation with its size). 这样,向量不必在每次增长时重新分配存储,而是仅在这个额外空间耗尽并且插入新元素时(这应该仅在与其大小相关的对数频率中发生)。

std::vector would reallocate itself with the increased capacity on demand -- ie when current capacity is exceeded (when size() == capacity() ). std :: vector将根据需求增加的容量重新分配自身 - 即当超过当前容量时(当size() == capacity() )。

How much capacity would be added, depend on the implementation: usually new_capacity = old_capacity * factor , where factor is somewhere from 1.5 to 2 (with theoretical ideal equals to Golden section ). 将添加多少容量取决于实现:通常new_capacity = old_capacity * factor ,其中factor从1.5到2(理论上理想等于Golden部分 )。 This is done so that pushing back new elements to the vector would have amortized constant time. 这样做是为了将新元素推回到向量中将具有分摊的恒定时间。

The standard guarantees which calls do not invalidate iterators. 该标准保证哪些调用不会使迭代器失效。 Technically, a std::vector could comply with the standard by only doing resizes that don't require copying the data to a new location, ie, that don't invalidate iterators. 从技术上讲, std::vector可以通过仅执行不需要将数据复制到新位置的调整大小来符合标准,即不会使迭代器无效。 I doubt anybody does, though. 不过,我怀疑是否有人这样做。

So, resizes happen on calls to reserve() or resize() or any other call that is documented as invalidating iterators. 因此,在调用reserve()resize()或任何其他被记录为使迭代器无效的调用时会发生resize()

http://www.sgi.com/tech/stl/Vector.html states http://www.sgi.com/tech/stl/Vector.html声明

Memory will be reallocated automatically if more than capacity() - size() elements are inserted into the vector. 如果向量中插入了多个capacity() - size()元素,则会自动重新分配内存。 Reallocation does not change size(), nor does it change the values of any elements of the vector. 重新分配不会更改size(),也不会更改向量的任何元素的值。 It does, however, increase capacity(), and it invalidates [5] any iterators that point into the vector. 但是,它会增加capacity(),并且会使指向向量的任何迭代器无效[5]。

I found these notes helpful: 我发现这些笔记很有帮助:

http://www.sgi.com/tech/stl/Vector.html#2 http://www.sgi.com/tech/stl/Vector.html#2

http://www.sgi.com/tech/stl/FAQ.html (Why does a vector expand its storage by a factor of two when it performs a reallocation?) http://www.sgi.com/tech/stl/FAQ.html (为什么向量在执行重新分配时会将其存储扩展两倍?)

However, this is the SGI STL, couldn't find g++ documentation. 但是,这是SGI STL,找不到g ++文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当 std::vector 重新分配其内存数组时,使用的是复制构造函数还是移动构造函数? - When std::vector reallocate its memory array, is copy constructor or move constructor used? std :: vector :: reserve是否重新分配内部数组? - Does std::vector::reserve reallocate the internal array? 什么时候std :: string重新分配内存? - When does std::string reallocate memory? 重新分配结构的std :: vector - Reallocate a std::vector of struct std :: vector在哪里分配其内存? - Where does a std::vector allocate its memory? std :: vector *在增加容量时是否有*移动对象?或者,分配器可以“重新分配”吗? - Does std::vector *have* to move objects when growing capacity? Or, can allocators “reallocate”? 当第一个向量重新分配时,另一个向量内的std :: vectors会重新分配吗? - Will std::vectors inside another vector reallocate when the first vector reallocates? 为什么std :: vector零会初始化其内存? - Why does std::vector zero initilize its memory? 在`std :: vector`调整其内存大小时避免任何自动变量 - Avoiding any automatic variables when `std::vector` resizes its memory 标准是否保证,如果新大小小于或等于旧大小,std :: string :: resize将不会重新分配内存? - Does the standard guarantee, that std::string::resize will not do reallocate memory, if the new size is less than or equal to as the old one?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM