使用std :: optional作为常规指针与使用has_value()和value

Gor*_*eng 1 c++ c++17 stdoptional

std::optional 可以使用语法来访问其值,类似于普通指针一样。

std::optional<string> some_str;
if (some_str)
    (*some_str).c_str();
Run Code Online (Sandbox Code Playgroud)

但它也有两个功能,has_value()value()提供访问其价值和检查,如果该值存在。

std::optional<string> some_str;
if (some_str.has_value())
    some_str.value().c_str();
Run Code Online (Sandbox Code Playgroud)

我想知道这两者之间有什么区别?
1.更冗长
2.性能?
3.更好的日志记录和调试?value()会抛出异常。

Bar*_*rry 6

这里有两件事。

首先,explicit operator bool() constvs bool has_value() const。这些恰好是同义词。他们的意思完全相同。使用您喜欢的任何一个。

第二,T& value()vs T& operator*()。这与vector :: at与vector :: operator []相同。前者没有先决条件-它检查并抛出-后者有先决条件-如​​果取消了可选的行为,则这是未定义的行为。


Ser*_*eyA 5

std::optional(没有实验性,C++17 就在我们身上)定义了两个不同的接口来访问它的可选成员:检查访问 ( std::optional::value) 和未检查访问 ( operator*)。

使用检查访问有两个潜在的缺点 - 首先,它会减慢执行速度,因为执行了分支,其次,如果值不存在,它将抛出异常,这在控制流方面可能是不可取的。虽然第二个问题可以通过std::optional::has_value在调用 value 之前显式检查 value present ( )来缓解,但运行时性能成本仍然存在。

未经检查的访问没有与此相关的性能成本,但只有在您通过其他方式知道该值存在时才能安全使用(即您has_value之前检查过)。否则,程序的行为是未定义的,我们不希望这样。

从上面可以明显看出,您显示的第二个代码段过多:

if (some_str.has_value())
    some_str.value().c_str();
Run Code Online (Sandbox Code Playgroud)

是否检查值存在两次(至少在语义上,编译器可能能够优化第二次检查)。不过,更清晰的代码是

if (some_str.has_value())
    some_str->c_str();
Run Code Online (Sandbox Code Playgroud)