std::unique_ptr
has support for arrays, for instance:
std::unique_ptr<int[]> p(new int[10]);
but is it needed? probably it is more convenient to use std::vector
or std::array
.
Do you find any use for that construct?
std::unique_ptr
has support for arrays, for instance:
std::unique_ptr<int[]> p(new int[10]);
but is it needed? probably it is more convenient to use std::vector
or std::array
.
Do you find any use for that construct?
An
std::vector
can be copied around, whileunique_ptr<int[]>
allows expressing unique ownership of the array.std::array
, on the other hand, requires the size to be determined at compile-time, which may be impossible in some situations.Contrary to
std::vector
andstd::array
,std::unique_ptr
can own a NULL pointer.This comes in handy when working with C APIs that expect either an array or NULL:
There are tradeoffs, and you pick the solution which matches what you want. Off the top of my head:
Initial size
vector
andunique_ptr<T[]>
allow the size to be specified at run-timearray
only allows the size to be specified at compile timeResizing
array
andunique_ptr<T[]>
do not allow resizingvector
doesStorage
vector
andunique_ptr<T[]>
store the data outside the object (typically on the heap)array
stores the data directly in the objectCopying
array
andvector
allow copyingunique_ptr<T[]>
does not allow copyingSwap/move
vector
andunique_ptr<T[]>
have O(1) timeswap
and move operationsarray
has O(n) timeswap
and move operations, where n is the number of elements in the arrayPointer/reference/iterator invalidation
array
ensures pointers, references and iterators will never be invalidated while the object is live, even onswap()
unique_ptr<T[]>
has no iterators; pointers and references are only invalidated byswap()
while the object is live. (After swapping, pointers point into to the array that you swapped with, so they're still "valid" in that sense.)vector
may invalidate pointers, references and iterators on any reallocation (and provides some guarantees that reallocation can only happen on certain operations).Compatibility with concepts and algorithms
array
andvector
are both Containersunique_ptr<T[]>
is not a ContainerI do have to admit, this looks like an opportunity for some refactoring with policy-based design.
In a nutshell: it's by far the most memory-efficient.
A
std::string
comes with a pointer, a length, and a "short-string-optimization" buffer. But my situation is I need to store a string that is almost always empty, in a structure that I have hundreds of thousands of. In C, I would just usechar *
, and it would be null most of the time. Which works for C++, too, except that achar *
has no destructor, and doesn't know to delete itself. By contrast, astd::unique_ptr<char[]>
will delete itself when it goes out of scope. An emptystd::string
takes up 32 bytes, but an emptystd::unique_ptr<char[]>
takes up 8 bytes, that is, exactly the size of its pointer.The biggest downside is, every time I want to know the length of the string, I have to call
strlen
on it.Some people do not have the luxury of using
std::vector
, even with allocators. Some people need a dynamically sized array, sostd::array
is out. And some people get their arrays from other code that is known to return an array; and that code isn't going to be rewritten to return avector
or something.By allowing
unique_ptr<T[]>
, you service those needs.In short, you use
unique_ptr<T[]>
when you need to. When the alternatives simply aren't going to work for you. It's a tool of last resort.Scott Meyers has this to say in Effective Modern C++
I think that Charles Salvia's answer is relevant though: that
std::unique_ptr<T[]>
is the only way to initialise an empty array whose size is not known at compile time. What would Scott Meyers have to say about this motivation for usingstd::unique_ptr<T[]>
?