根据 Cppreference,optional::value()
onstd::nullopt
会抛出异常,而解引用an optional
which 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->
因为 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()
.