Search code examples
c++undefined-behaviorstdoptional

Why is it undefined behavior to call operator* on an empty std::optional if I don't access the returned value right away?


Why is it undefined behavior to call operator* on an empty std::optional if I don't access the returned value before emplacing an object?

For example, why is the following code UB?

std::optional<int> opt_val;
auto p_val = &(*opt_val);
opt_val.emplace(0);
    
// do something with p_val

EDIT: Original question asked if it was UB, now asking why it is UB.


Solution

  • Because the standard says so. Not explicitly, but 22.5.3.6#1 says about operator*:

    Preconditions: *this contains a value.

    The standard does not define what happens when you call the function while the precondition is not met. It is undefined.

    Actually that could make the answer already. The standard does not try to define all and everything. Instead it specifies what a method does when it is used for what it is supposed to be used for. Calling std::optional::operator* without using the result has no use. The method could even be marked as [[nodiscard]] to make it an error when the value returned is ignored. What the standard does not define is undefined.


    std::optional does not use dynamic allocations. It models an object, not a pointer. Nevertheless calling operator* on a optional that does not contain an object is similar to dereferencing a null pointer.

    I suppose it would be possible to write an implementation that has no issues with calling operator* on an empty optional. Though, the standard says that it is undefined, hence an implementation does not have to deal with it. That gives more freedom to implementations, and potentially grants more opportunities to the optimizer.