vector<unique_ptr> resizing with push_back - how does it work?

c++, c++11, memory, smart-pointers, vector

Solution

resulting in copying all the elements into it from the old memory block, calling their destructors. Since unique_ptr destructors delete the owned memory, how is it possible that they work with vector?

In fact, it's not strictly copying the elements any more, it is moving. For types that have no implicit or explicit move constructor, that's the same. But for `unique_ptr`s that means, new `unique_ptr`s are constructed in the newly allocated memory, given an rvalue-reference to the "old" `unique_ptr`s. Their move constructor does the right thing, i.e. it transfers ownership from the old to the new `unique_ptr`s, leaving the old ones empty so nothing gets deleted when they are destroyed.

Is it safe to use unique_ptr in vectors?

It's save to use `unique_ptr`s everywhere, as long as you respect language rules and "C++ common sense". That means, you will have to explicitly do stupid things to break `unique_ptr`s safe behavior. Among those are e.g. pretending to give ownership of the owned object to yet another smart pointer:

unique_ptr<T> ptr1 {new T()};
unique_ptr<T> ptr2 {ptr1.get()}; //two unique_ptr's owning the same object...

or some destructive actions involving `reinterpret_cast`, `memcpy`, `memset` or other stuff that don't respect C++ object lifetimes.

Is it slower than regular pointers?

Maybe. There is clearly some small overhead involved when moving a `unique_ptr` in comparison to copying a raw pointer, namely setting the original to zero. But whether that overhead can be optimized away or not depends on your compiler and optimizer. And as ever with performance, consult your profiler to assess whether it is slower and whether the slowdown matters. I bet it won't, and taking into account the amount of security the smart pointers will give you, just never ask about `unique_ptr`'s performance.

Sidenote: If you know the size of your vector in advance, remeber to use `vector::reserve()`. It will save you the reallocations and moves of the `unique_ptr`s. And if you know only the approximate size your vector will have, don't be petty - `unique_ptr`s are not very big (normally as big as a raw pointer plus the deleter, which might or might not be optimized away), so reserving a few percent more won't hurt unless you really have tight memory constraints.

Problem

As far as I understand, when stuff is pushed_back into a vector, sometimes it has to allocate a new memory block, resulting in copying all the elements into it from the old memory block, calling their destructors. Since unique_ptr destructors delete the owned memory, how is it possible that they work with vector? Is it safe to use unique_ptr in vectors? Is it slower than regular pointers?

Original source