Reputation: 2440
Here is a motivating example demonstrating what my problem is:
struct Foo
{
int x;
int y;
};
boost::optional<Foo> opt_foo;
opt_foo->x = 1; // legal
opt_foo->y = 2; // legal
auto foo = opt_foo.get(); // legal (returns valid instance of Foo with x = 1 and y = 2)
if (opt_foo) // false
{
...
}
I understand that in order for the optional object to be initialized, I would have to use boost::optional<Foo> opt_foo = Foo();
. However, I was surprised to see that if it is forgotten, I can still do all the things I marked as legal (especially get()
). Was this intended behavior? Is there any way I can make opt_foo
consider itself initialized without boost::optional<Foo> opt_foo = Foo();
?
Upvotes: 0
Views: 908
Reputation: 133567
Under the hood, boost::optional
is implemented as a simple
struct {
bool _present;
T _t;
}
So whether you explicitly initialize or not the optional with a value, the storage for this value already exists, and in C++ we don't usually like to pay for what we don't need (eg. checking if an optional is present on each call of operator->
).
It is duty of the developer to only try to access the optional value if it is present, as explained in the documentation:
An attempt to extract the contained value of an uninitialized optional object is an undefined behaviour (UB). This implementation guards the call with
BOOST_ASSERT
. Therefore you should be sure that the contained value is there before extracting.
Actually your code should SIGABRT
on the assertion, are you running it in debug mode?
You can use value()
if you want to avoid any risk of UB (but you need to place that in a try
block).
Upvotes: 1