0

I'm trying to create a hiearchy of classes in which parts are optional. I would like things to automatically be created as soon as variables are set.

For that I use C++17 std::optional feature.

Now in the example below I forgot to set the "parent" (test2_inst) first, yet g++, clang and msvc all compile and run fine altough with the "not set" output.

My questions now are: am I indeed doing the wrong thing in this example? and what would the proper way of resolving this? Or are the compilers doing the wrong thing?

#include <optional> class test1 { public: class test2 { public: int a, b; class test3 { public: int c, d; }; test3 test3_inst; }; std::optional<test2> test2_inst; }; int main(int argc, char *argv[]) { test1 *test1_inst = new test1(); // can set value test1_inst->test2_inst->test3_inst.c = 3; // yet optional says it is note set? if (test1_inst->test2_inst.has_value()) printf("set\n"); else printf("not set\n"); return 0; } 
6
  • 3
    You are using uninitialized variable, which is undefined behavior. That means anything can happen, including correct behavior. Commented Dec 9, 2019 at 10:13
  • @vll which variable is uninitialized? Commented Dec 9, 2019 at 10:22
  • All the memory is stored inside the optional, it's not heap allocated. So you're not going to get a segfault if it's nullopt if the compiler allows it. But the data in there will be incorrect Commented Dec 9, 2019 at 10:29
  • 1
    Semi-related: Nothing in C++ is ever guaranteed to crash, so asking "shouldn't this crash?" is always wrong Commented Dec 9, 2019 at 10:38
  • 1
    @UnholySheep Off topic: by default, std::terminate calls std::abort which is considered a crash. It is well defined that if you don't catch an exception then std::terminate will be called, so C++ some things are warranted to crash your program. Commented Dec 9, 2019 at 11:00

2 Answers 2

4

The behaviour of optional::operator* and optional::operator-> is undefined if the optional does not contain a value.

Accesses the contained value.

  1. Returns a pointer to the contained value.
  2. Returns a reference to the contained value.

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

Source: https://en.cppreference.com/w/cpp/utility/optional/operator*

Sign up to request clarification or add additional context in comments.

Comments

1

shouldn't this crash?

Could. Undefined behavior can do anything. Crashing is one possibility. Not crashing and appearing to work is also a possibility.

am I indeed doing the wrong thing in this example?

Yes.

what would the proper way of resolving this?

Depends what you are trying to do. Check the optional...

if (test1_inst->test2_inst) test1_inst->test2_inst->test3_inst.c = 3; 

Or, assign its value...

test1_inst->test2_inst = test1::test2{1, 2, {3, 4}}; 

Or are the compilers doing the wrong thing?

No, the C++ standard gives the compilers a lot of latitude.

C++ is not a nanny language, and gives programmers enough rope to shoot themselves in the foot.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.