c++language-lawyerstdvector

Is it safe to use `vec.push_back(vec.back());`?


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());

Solution

  • 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.