1 minute read

Categories:

Tags:

std::optional defined in <optional> header.

  1. standard optional is never going to do a dynamic allocation on its own. Its constructed to be at least big enough to hold the thing that you want it to hold.
#include <optional>

int main()
{
    std::optional<int> i;
    return sizeof(i);   // have size of 8byte = size of 32bit integer + 4byte

    std::optional<double> d;
    d = 3.4; // no dynamic allocation happening
    return sizeof(i);
}

what optional does is it is optionally set to a value it keeps track of whether or not that value is set and then it appropriately calls the destructor if it needs to.

optional::value, optional::value_or

#include <optional>

int main()
{
    std::optional<int> o;
    return o.value();
}

If we donโ€™t set any value to o, we get tones of assembly instructions for handling exception.


std::optional<int> o;
return o.value_or(2);

if we use value_or like this, if o has a value it returns the value else it returns the value 2.

interesting behavior

#include <optional>

int main()
{
    std::optional<int> o;
    o = 12; // assigns the unset value of optional to 12
    o = 14; // calling the assignment operator on the integer
    return o.value_or(2);
}

In the case of integer calling an assignment is not really expensive, but in other cases like string, the code will be much more unlikely to optimize.

#include <optional>
#include <string>

int main()
{
    std::optional<std::string> o;
    o = std::string("Hello"); //move assignment here
    return o.value().size();
}

What would happen if we have a type that cannot be moved or copied.

#include <optional>
#include <string>

struct S
{
    S(const& S&) = delete;
    S(S&&) = delete;
    S() = default;
}

int main()
{
    std::optional<S> o;
    o = S(); //build error!! 

}

however we could do emplace construction like o.emplace() and it will construct our new object s in place inside optional avoiding any cost of move or copy at all.

Leave a comment