Suppose I write
std::vector littleVector(1);
std::vector bigVector;
bigVector.reserve(100);
bigVector = littleVector;
Does t
Unfortunately, the standard underspecifies behavior on allocator-aware sequence container assignment, and indeed is strictly speaking inconsistent.
We know (from Table 28 and from 23.2.1p7) that if allocator_traits
is true
then the allocator is replaced on copy assignment. Further, from Tables 96 and 99 we find that the complexity of copy assignment is linear, and the post-condition on operation a = t
is that a == t
, i.e. (Table 96) that distance(a.begin(), a.end()) == distance(t.begin(), t.end()) && equal(a.begin(), a.end(), t.begin())
. From 23.2.1p7, after copy assignment, if the allocator propagates, then a.get_allocator() == t.get_allocator()
.
With regard to vector capacity, 23.3.6.3 [vector.capacity] has:
5 - Remarks: 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 value ofcapacity()
.
If we take library DR341 as a guide to reading the Standard:
However, the wording of 23.3.6.3 [vector.capacity]paragraph 5 prevents the capacity of a vector being reduced, following a call to reserve(). This invalidates the idiom, as swap() is thus prevented from reducing the capacity. [...]
DR341 was resolved by adding paragraphs into 23.3.6.3:
void swap(vector
& x);
7 - Effects: Exchanges the contents andcapacity()
of*this
with that ofx
.
8 - Complexity: Constant time.
The conclusion is that from the point of view of the Library committee, operations only modify capacity()
if mentioned under 23.3.6.3. Copy assignment is not mentioned under 23.3.6.3, and thus does not modify capacity()
. (Move assignment has the same issue, especially considering the proposed resolution to Library DR2321.)
Clearly, this is a defect in the Standard, as copy assignment propagating unequal allocators must result in reallocation, contradicting 23.3.6.3p5.
We can expect and hope this defect to be resolved in favour of:
capacity()
on non-allocator-modifying copy assignment;capacity()
on allocator-modifying copy assignment;capacity()
on non-allocator-propagating move assignment;capacity()
on allocator-propagating move assignment.However, in the current situation and until this is clarified you would do well not to depend on any particular behavior. Fortunately, there is a simple workaround that is guaranteed not to reduce capacity()
:
bigVector.assign(littleVector.begin(), littleVector.end());