Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is use of empty std::optional<string> UB or not?

Tags:

c++

The following code:

    std::optional<std::string> so;
    std::cout << so->size() << std::endl;
    std::cout << so.has_value();

outputs:

   0
   0  

My question is whether its safe to call : so->size() on an empty optional. I used clang sanitizer, but it didnt report any UB in above code.

like image 965
mike Avatar asked Nov 10 '20 20:11

mike


People also ask

When to use optional c++?

A common use case for optional is the return value of a function that may fail. 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.

Does STD optional allocate memory?

What's more, std::optional doesn't need to allocate any memory on the free store. std::optional is a part of C++ vocabulary types along with std::any , std::variant and std::string_view .

What is Nullopt in C++?

C++17 introduced std::optional<T> which lets you augment the values of a type T with a bonus value known as std::nullopt which semantically represents the absence of a value. A std::optional which holds the value std::nullopt is known as empty.


3 Answers

Using operator-> on an empty std::optional is Undefined Behavior, regardless of what type T is in std::optional<T>.

According to cppreference on std::optional<T>::operator-> :

The behavior is undefined if *this does not contain a value.

like image 176
François Andrieux Avatar answered Oct 23 '22 09:10

François Andrieux


Quoting the current C++ working draft

20.6.3.6 Observers [optional.observe]

constexpr const T* operator->() const;
constexpr T* operator->();

Preconditions: *this contains a value.


Then:

16.3.2.4 Detailed specifications [structure.specifications]

Preconditions: the conditions that the function assumes to hold whenever it is called; violation of any preconditions results in undefined behavior.

Thus, it's undefined behavior.

like image 39
Tony Tannous Avatar answered Oct 23 '22 08:10

Tony Tannous


You're calling the default optional constructor (1 in that link), which...

  1. Constructs an object that does not contain a value.

When you go to dereference...

The behavior is undefined if *this does not contain a value.

Which in your case it doesn't. So yes, you have UB.

like image 3
scohe001 Avatar answered Oct 23 '22 08:10

scohe001