Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What to use std::optional or std::unique_ptr

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

like image 445
Victor Aurélio Avatar asked Jul 01 '17 01:07

Victor Aurélio


People also ask

When should we use 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.

What is std :: optional used for?

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.

Does std :: optional use heap?

First of all, it doesn't require allocation on the heap -- it can be stored along side other data.

Does std optional allocate memory?

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.


1 Answers

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.

like image 88
AnT Avatar answered Oct 05 '22 23:10

AnT