为什么我们需要 std::nullopt

Seb*_*ann 5 c++ c++17

什么时候我们可以使用统一初始化来轻松地默认构造一个std::optional<T>?

std::optional<T> foo() {
   if (on_error)
      return {};

    // ...
}
Run Code Online (Sandbox Code Playgroud)

以上有什么缺点可以std::nullopt解决吗?

Ast*_*ngs 9

不。

这是默认构造optional.

即使对于分配,您也可以复制分配一个默认构造的optionalwith= {}而不是 using std::nullopt

cppreference 实际上说了这么多

nullopt_t的构造函数上的约束同时支持op = {};op = nullopt;作为脱离可选对象的语法。

...与该功能的原始提案一样

请注意,这不是脱离可选对象的唯一方法。您还可以使用:

op = std::nullopt;
Run Code Online (Sandbox Code Playgroud)

你可能会问自己,为什么std::nullopt存在。该提案也解决了这个问题

它在接口中引入了冗余

【类似例子】

另一方面,有一些用法不能用任何其他方便的符号代替 nullopt 的用法:

void run(complex<double> v);
void run(optional<string> v);

run(nullopt);              // pick the second overload
run({});                   // ambiguous

if (opt1 == nullopt) ...   // fine
if (opt2 == {}) ...        // illegal

bool is_engaged( optional<int> o)
{
  return bool(o);          // ok, but unclear
  return o != nullopt;     // familiar
}
Run Code Online (Sandbox Code Playgroud)

虽然在某些情况下可以使用 {} 语法,但使用 nullopt 会使程序员的意图更加明确。比较这些:

optional<vector<int>> get1() {
  return {};
}

optional<vector<int>> get2() {
  return nullopt;
}

optional<vector<int>> get3() {
  return optional<vector<int>>{};
}
Run Code Online (Sandbox Code Playgroud)

简而言之,std::nullopt可能很有用,但就您而言,它只是归结为风格。