我正在尝试创建一个类的层次结构,其中部分是可选的。我希望在设置变量后立即自动创建事物。
为此,我使用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;
}
答案 0 :(得分:4)
如果optional
不包含值,则未定义optional :: operator *和optional :: operator->的行为。
访问包含的值。
- 返回指向包含值的指针。
- 返回对包含值的引用。
如果
*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 ++不是一种保姆语言,它为程序员提供了足够的绳索来使自己陷入困境。