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?
According to cppreference, one of the use cases for std::unique_ptr
is use in "move-aware containers", such as std::vector
. This implies that std::vector<T>
is smart enough to detect when T
is movable, which is the case for std::unique_ptr
, and use the move constructor when resizing the vector.
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.
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