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?
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
.
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 ofget_allocator()
shall be the same as the value ofrv.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