Is the capacity required to be preserved when moving a std::vector?

孤人 提交于 2019-12-05 10:31:25

问题


Consider the following code:

std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();

std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());

In pretty much any implementation you run across, this will work. I don't care about what implementations do. I want to know what the standard requires. Will the moved-to vector have the same capacity as the original? Or will the assert trigger?


回答1:


Looking at the standard, it appears that nothing is required from the move constructor, however as @amaurea says, it would completely defeat the purpose of move semantics if the move constructor were to try and allocate or deallocate memory, so I would expect the capacity to remain the same in all implementations.


23.2.1 General container requirements

Expression

X u(a);
X u = a;

Assertion/note pre-/post-condition

Requires: T is CopyInsertable into X (see below).
post: u == a


The standard only requires that newVec == vec. As capacity is not taken into consideration for std::vector::operator==, newVec need not necessarily have the same capacity as vec.




回答2:


C++11 standard requirements on move constructor for std::vector are (Table 99 — Allocator-aware container requirements):

X(rv)
X u(rv)
  • move construction of allocator shall not exit via an exception
  • post: u shall have the same elements as rv had before this construction; the value of get_allocator() shall be the same as the value of rv.get_allocator() before this construction.
  • complexity: constant

Here is no requirements/guarantee on capacity. But we can make conclusion that constant complexity implicitly denies any reallocations. And I cannot see any other logical reason to change capacity except reallocation. So it shall be the same.

From the other point of view if the moved-from vector is empty, it is perfectly legal to just ignore it and default-construct itself. This would still be O(1), as it doesn't require any per-element constructs. (Thanks to Nicol Bolas for this issue).

Also implemenation possibly could shrink capacity to the size using hint parameter of std::allocator::allocate function:

pointer allocate(size_type, allocator<void>::const_pointer hint = 0);

The use of hint is unspecified, but intended as an aid to locality if an implementation so desires. So some sofisticated solution possibly could pass vector storage pointer as hint and use realloc on it to shrink capacity.

Conclusion: looks like standard doesn't guarantee capacity preserving on moving std::vector, storage potentially could be shrinked.



来源:https://stackoverflow.com/questions/13129219/is-the-capacity-required-to-be-preserved-when-moving-a-stdvector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!