std :: optional&编译器-这不应该崩溃吗?

时间:2019-12-09 10:10:26

标签: c++ c++17

我正在尝试创建一个类的层次结构,其中部分是可选的。我希望在设置变量后立即自动创建事物。

为此,我使用C ++ 17 std :: optional功能。

现在在下面的示例中,我忘记了首先设置“父”(test2_inst),但是g ++,clang和msvc都可以编译并在“未设置”输出的情况下正常运行。

我现在的问题是:在这个例子中我确实做错了吗?解决该问题的正确方法是什么? 还是编译器做错了事?

#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;
}

2 个答案:

答案 0 :(得分:4)

如果optional不包含值,则未定义optional :: operator *和optional :: operator->的行为。

  

访问包含的值。

     
      
  1. 返回指向包含值的指针。
  2.   
  3. 返回对包含值的引用。
  4.   
     

如果*this不包含值,则行为未定义。

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

答案 1 :(得分:1)

  

这难道不是吗?

可以。未定义的行为可以做任何事情。崩溃是一种可能。也不会崩溃并看上去可以正常工作。

  

在这个例子中我确实做错了吗?

是的

  

解决这个问题的正确方法是什么?

取决于您要执行的操作。检查可选的...

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

或者,分配其值...

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

还是编译器做错了事?

不,C ++标准为编译器提供了很大的自由度。

C ++不是一种保姆语言,它为程序员提供了足够的绳索来使自己陷入困境。