C++17 has introduced a very useful template class, std::optional
:
The class template
std::optional
manages an optional contained value, i.e. a value that may or may not be present.
I have been using this feature a lot since 2017, even for a simple optional integer. Today, I got curious: is this template type effective compared to an equivalent type that I would write myself to achieve the same behavior?
Good question, thank you 😆
Let's try to write some code and use Compiler Explorer to compare both solutions: std::optional
vs custom type for optional value.
First, let's define two equivalent types:
#include <optional>
using StdOptionalInt = std::optional<int>;
struct CustomOptionalInt {
bool has_value;
int value;
};
Then, let's write two functions that test if the value is available and return either this value (if available) or a default value (if not available):
int getStdOptional(const StdOptionalInt& o) {
return o.has_value() ? o.value() : 0;
}
int getCustomOptional(const CustomOptionalInt& o) {
return o.has_value ? o.value : 0;
}
Finally, compile the code with Compiler Explorer and compare the output assembly codes (you can try by yourself here):
Yeah! 😃 The 2 functions generate the same assembly code. There is no difference of performance. Notice the static assertion at the end of the source code: because the code compiles, it means the footprint are the same. The behavior is the same with gcc and clang for x86-64.
As a conclusion, std::optional
is as efficient as a custom type to represent an optional integer value. Don't implement your own type, simply use the standard type. You may even get better performance using std::optional
, as explained on cppreference:
As opposed to other approaches, such as
std::pair<T,bool>
,optional
handles expensive-to-construct objects well and is more readable, as the intent is expressed explicitly.
By the way, if you happen to speak French:
- I wrote an article to explain to how to use std::optional.
- I made a video to present Compiler Explorer.