If your question had been about move construction of a vector
, the answer would be easy, the source vector
is left empty after the move. This is because of the requirement in
Table 99 — Allocator-aware container requirements
Expression:
X(rv)
X u(rv)
Requires: move construction of A
shall not exit via an exception.
post: u
shall have the same elements as rv
had before this construction; the value of u.get_allocator()
shall be the same as the value of rv.get_allocator()
before this construction.
Complexity: constant
(the A
in the requirements clause is the allocator type)
The constant complexity leaves no option but to steal resources from the source vector
, which means for it to be in a valid, but unspecified state you'd need to leave it empty, and capacity()
will equal zero.
The answer is considerably more complicated in case of a move assignment. The same Table 99 lists the requirement for move assignment as
Expression:
a = rv
Return type:
X&
Requires: If allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
is
false
, T is MoveInsertable
into X
and MoveAssignable
. All existing elements of a
are either move assigned to or destroyed.
post: a
shall be equal to the value that rv
had before this assignment.
Complexity: linear
There are different cases to evaluate here.
First, say allocator_traits<allocator_type>::propagate_on_container_move_assignment::value == true
, then the allocator can also be move assigned. This is mentioned in §23.2.1/8
...
The allocator may be replaced only via assignment or swap()
. Allocator replacement is performed by copy assignment, move assignment, or swapping of the allocator
only if allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value
,
allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
, or allocator_traits<allocator_type>::propagate_on_container_swap::value
is true within the implementation of the corresponding container operation.
So the destination vector
will destroy its elements, the allocator from the source is moved and the destination vector
takes ownership of the memory buffer from the source. This will leave the source vector
empty, and capacity()
will equal zero.
Now let's consider the case where allocator_traits<allocator_type>::propagate_on_container_move_assignment::value == false
. This means the allocator from the source cannot be move assigned to the destination vector
. So you need to check the two allocators for equality before determining what to do.
If dest.get_allocator() == src.get_allocator()
, then the destination vector
is free to take ownership of the memory buffer from the source because it can use its own allocator to deallocate the storage.
Table 28 — Allocator requirements
Expression:
a1 == a2
Return type:
bool
returns true
only if storage allocated from each can be deallocated via the other. ...
The sequence of operations performed is the same as the first case, except the source allocator is not move assigned. This will leave the source vector
empty, and capacity()
will equal zero.
In the last case, if allocator_traits<allocator_type>::propagate_on_container_move_assignment::value == false
and dest.get_allocator() != src.get_allocator()
, then the source allocator cannot be moved, and the destination allocator is unable to deallocate the storage allocated by the source allocator, so it cannot steal the memory buffer from source.
Each element from the source vector
must be either move inserted or move assigned to the destination vector
. Which operation gets done depends on the existing size and capacity of the destination vector
.
The source vector
retains ownership of its memory buffer after the move assignment, and it is up to the implementation to decide whether to deallocate the buffer or not, and the vector
will most likely have capacity() greater than 0
.
To ensure you do not run into undefined behavior when trying to resuse a vector
that has been move assigned from, you should first call the clear()
member function. This can be safely done since vector::clear
has no pre-conditions, and will return the vector
to a valid and specified state.
Also, vector::capacity
has no pre-conditions either, so you can always query the capacity()
of a moved from vector
.