Is it guaranteed that std::vector
only moves its data when size()==capacity()
and calling push_back()
or emplace_back()
or can it do it otherwise also?
The C++ function std::vector::emplace_back() inserts new element at the end of vector. Reallocation happens if there is need of more space. This method increases container size by one.
Calling emplace_back will call the move constructor of std::string when std::move is used, which could save on a copy (so long as that string isn't stored in a SSO buffer). Note that this is essentially the same as push_back in this case.
With the simple benchmark here, we notice that emplace_back is 7.62% faster than push_back when we insert 1,000,000 object (MyClass) into an vector. Insert 1,000,000 objects.
The specification is a bit indirect. capacity
is specified as:
size_type capacity() const noexcept;
Returns: The total number of elements that the vector can hold without requiring reallocation.
The second part comes from reserve
:
reserve(size_type n);
Remarks: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. No reallocation shall take 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()
.
From that you can conclude that if the size is less than the capacity, then insertion does not cause reallocation.
There is no single, direct statement that the vector will not reallocate if there is spare capacity and you haven't explicitly called reserve
. However, there is a general container requirement in [container.requirements.general]:
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.
Finally, we have description of the effects of insertion:
[insert/emplace_back/push_back:]
Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens, all the iterators and references before the insertion point remain valid.
Putting it all together: Unless otherwise specified, calling a member function does not invalidate iterators. Reallocation invalidates iterators (as described as part of reserve
above), so unless otherwise specified, calling a member function, and in particular an insertion, does not reallocate, One such an overriding specification is given for the case where the new size exceeds the current capacity.
The description of standard is not clear enough.
$23.3.6.5 vector modifiers [vector.modifiers]:
Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens, all the iterators and references before the insertion point remain valid.
So when add elements to std::vector
reallocation will certainly happen when the new size is greater than current capacity, but it doesn't says reallocation won't happen even if the new size is less than or equal to current capacity. Anyway if reallocation doesn't happen then all the iterators and references to the elements before the insertion point must remain valid, implies data won't be moved.
It's the same for insert()
, emplace_back()
, emplace()
and push_back()
.
Quote from cppreference.com just as reference:
If the new
size()
is greater thancapacity()
then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With