std::vector<T,A>( std::vector<T,A>&& )
this is guaranteed to be constant time (N3797 Table 99 X u(rv)
).
There is no way known to myself to move an arbitrary sized vector in constant time without just moving the pointers to the buffer. If this (there is no way) is true, then the constructed vector must have a buffer at least as larger as the source buffer. There is no wording in the standard that states vector
s need be efficient, however: the right hand side vector
can have its capacity reduced to any value greater than or equal to its size
: the postcondition is only that the elements are the same. In theory it could even be larger capacity, if the right hand side vector
had "hidden capacity" that the compiler chose to expose for whatever reason (the phase of the moon, say).
At no point in the N3797 standard is an upper bound on capacity
placed on any container. A conforming implementation can have all std::vector
s have a minimum 2 million element capacity (barring allocator
failure -- which could be used to force a capacity of 0
), with no operation capable of reducing that value below 2 million. (shrink_to_fit
is just a suggestion, and std::vector<T,A>().swap(x)
could create a vector
of 2 million capacity and swap it.
As much of the above is of a negative form, all I can say is search the standard for every mention of vector
, allocator
, allocate
, and capacity
. capacity
is never described with an upper bound at any point. No restrictions (other than exception-safety) are made against extra calls to the allocator
in an empty std::vector
constructor (if the allocator
failed, you might have to stay size 0 and capacity 0, but extracting that state to anything that doesn't use the same allocator
is challenging).
As for copy assignment and move assignment, the copy assignment places no guarantees on capacity beyond the most basic (that capacity() >= size()
).
For move-assignment, it depends on how this applies:
23.2.1 [container.requirements.general] /10
Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a
container member function or passing a container as an argument to a library function shall not invalidate
iterators to, or change the values of, objects within that container.
a = rv
(aka std::vector<T,A>& operator=(std::vector<T,A>&&)
) case from Table 96 and Table 99 are what concern us. Neither mention that the values contained in rv
are destroyed, nor that iterators to them are invalidated. As such, under 23.2.1/10 the iterators are not invalidated.
This does not, however, demand that the buffer be moved. Either the buffer is moved from the rhs to the lhs, or it remains intact in the rhs vector
. Table 99 mentions that case implicitly when it says that the lhs items can be move-assigned to (which is the only way a std::array
can work).
As std::array
has no choice but to move elements, and std::vector
gives no further guarantees about moving the buffer, the buffer does not have to be moved. It appears that moving the buffer is a legal implementation, however.
In practice, std::vector<T,A>( std::vector<T,A> const& )
will perform a copy of the contents of the right hand side into the left hand side, and in every implementation I have checked the left hand side's capacity
is equal to the size
of the resulting vector
. Similarly, std::vector<T,A>( ForwardIterator, ForwardIterator )
will produce a vector
that just-fits its input.
Note that std::vector<T,A>::operator=(std::vector<T,A>&&)
remains linear in complexity.