Another example of a use for std::make_optional()
would be for constructing the object stored in a std::optional
without creating a temporary for it when its constructor takes multiple arguments.
For example, consider the following Point3D
class whose constructor has multiple arguments:
struct Point3D {
Point3D(int xx, int yy, int zz): x(xx), y(yy), z(zz) {}
int x, y, z;
};
Imagine that you want to initialize the object stored by a std::optional<Point3D>
to Point3D(1, 2, 3)
X, then you could proceed as:
std::optional oPoint = Point3D(1, 2, 3);
However, this would create a Point3D
temporary object that is then moved into the std::optional
. Instead, by using the std::make_optional()
convenience function template you can avoid the creation of that temporary:
auto oPoint = std::make_optional<Point3D>(1, 2, 3);
Since we are talking about C++17 here (i.e., std::optional
was introduced in C++17), guaranteed copy elision applies here, and therefore no Point3D
temporary object is created.
Note that you can still avoid the creation of the temporary object without using std::make_optional()
by passing std::in_place
to the constructor of the std::optional<Point3D>
object:
std::optional<Point3D> oPoint{std::in_place, 1, 2, 3};
This will construct the stored Point3D
object in place, thus avoiding the creation of a temporary. Nevertheless, you may find this more verbose than the approach with std::make_optional()
.
Xstd::optional<Point3D> oPoint(1, 2, 3);
doesn't compile.
make_unique
andmake_shared
, they are still needed for reasons of leak free memory" - that is not why those functions exist. They exist to createunique_ptr
/shared_ptr
objects more efficiently (especiallyshared_ptr
) than creating them with raw pointers passed to their constructors. – Wringervoid func(std::unique_ptr<int>, std::unique_ptr<int>);
and then call itfunc(std::unique_ptr<int>(new int(42)), std::unique_ptr<int>(new int(13));
, you can get a memory leak, because the compiler is allowed to make calls in this order:new
,new
,unique_ptr ctor
,unique_ptr ctor
. If the secondnew
throws, the first allocation is leaked. If you callfunc(std::make_unique<int>(42), std::make_unique<int>(13));
, the calls tonew
and the calls to theunique_ptr
ctor can not get separated. – Decoration