当“*this”无效时,为什么 std::Optional 中的“operator->”会导致 UB?

cal*_*vin 3 c++

根据 Cppreference,optional::value()onstd::nullopt会抛出异常,而解引用an optionalwhich isstd::nullopt是 UB。

我有测试,似乎UB在某些编译器中可能不会panic,这比panic更可怕,所以如果错误使用它是非常有害的。我并不是说 UB 是好的或有意义的,但是,它是一个错误,如果发生的话,错误的结果比恐慌更难调试。

struct I {
    int get() { return 1; }
};

void f() {
    try {
        std::optional<std::shared_ptr<I>> x = std::nullopt;
        printf("%d\n", (*x)->get()); // -----> UB
    }
    catch (std::bad_optional_access & e) {
        printf("it throws in f\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么std::optional设计为导致 UB 而不是像/value()那样抛出异常?operator*operator->

for*_*818 9

因为 C++ 不会让你为不需要的东西付费。

检查如果std::optional持有某个值是有成本的。这只是一个简单的条件,也只有一个分支,但是当您确定存在一个值并且需要经常访问该值时,该条件和分支可能很重要。

如果您确定可选值包含值,则无需检查它是否包含值。

 // ...
 std::optional<int> x = 42; 
 for (int i=0;i<100000; ++i) {
          foo(*x);
 }
Run Code Online (Sandbox Code Playgroud)

在每次迭代中检查是否x包含int. 其他时候,您希望抛出异常,然后可以使用value().

  • 如果您想要测试和无异常保证,您可以使用 `x.has_value()` 手动测试并使用 `*x` 访问 (4认同)