I have a class with a member that is dynamic allocated (it's allocated only when it will be used).
Think something like that:
class A {};
class B {
A* aMember;
};
what would be better to replace A*
: std::optional
or std::unique_ptr
?
and when to use std::optional
instead std::unique_ptr
When to use unique_ptr? Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another.
We use std::optional to make our code more expressive. std::optional contains the object within itself, depending on where it is stored (stack/data/heap) std::optional makes a copy of the contained object.
First of all, it doesn't require allocation on the heap -- it can be stored along side other data.
optional is required to not use dynamic allocation. If an optional contains a value, the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place.
std::optional<A>
guarantees that no auxiliary memory allocation will take place. This means that the raw buffer for the potential object of type A
is embedded into std::optional<A>
. It is an integral part of std::optional
's memory footprint. This means that the memory size of std::optional<A>
will always be at least sizeof(A)
, regardless of whether that optional A
object currently lives or not. That is how much std::optional<A>
will contribute to the total size of B
.
std::unique_ptr<A>
is a pointer. Its size is about the same as the size of a regular naked pointer. That is how much memory std::unique_ptr<A>
itself occupies inside B
. In order to make it point to a valid A
object you will have to allocate that A
elsewhere, independently. When A
exists, it occupies memory. When A
does not exist it does not occupy memory.
The above is something to take into account when making your decision. std::optional<A>
does not involve dynamic memory allocation/deallocation, but the price you pay for that is potentially "wasted" memory inside your std::optional<A>
. Using std::optional
for massively instantiated and/or large objects might prove to be quite wasteful, especially if the object spends most of its lifetime in empty state.
This means that the purpose of std::optional
is not exactly aimed at optional long-term storage. std::optional
is something to be used locally: e.g. as optional local values, optional parameters of functions, optional return values. Long-term use is also OK, as long as you are not instantiating such objects in massive numbers.
std::unique_ptr<A>
does not waste memory, but the price you pay for that is dynamic memory allocation/deallocation.
Of course, ownership semantics is also quite different. std::optional
is copyable. std::unique_ptr
is movable, but not copyable.
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