I noticed that the parameter of vector<T>::push_back
is const T&
. I know that a reallocation may take place when I call push_back, but vector<T>::back
returns a reference. So is it safe?
std::vector<std::string> s{"some string"s};
s.push_back(s.back());
Yes, it is safe, assuming that the vector is not initially empty. push_back
must be implemented in such a way that it works, because there is no precondition placed on push_back(const T&)
to a different effect.
However, it is important to note that
s.push_back(std::move(s.back()));
would not be safe. The standard library may assume that a rvalue reference parameter of a library call always is the only reference to the object it is bound to. (This isn't specific to push_back
, but stated in generality in the library specification.)
The standard library implementation can (and does) make this work by copy-constructing the new element first into the new allocation before relocating the old elements of the vector.
See e.g. here for libc++, here for Microsoft's implementation or here for libstdc++'s implementation.
There is no problem with exception guarantees. If the copy constructor for the new element throws, then the old allocation is still in place with all of its original contents.