提问者:小点点

为什么我们需要std::nullopt[重复]


当我们可以使用统一初始化轻松地默认构造std::optional时?

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

    // ...
}

std::nullopt解决了上面的缺点吗?


共2个答案

匿名用户

不。

这是一种非常有效的默认构造可选的方法。

即使是分配,也可以使用={}复制分配默认构造的optional,而不是使用std::nullopt:

cppreference实际上也是这么说的:

存在对nullopt_t构造函数的约束,以支持op={};op=nullopt;作为分离可选对象的语法。

。。。功能的原始提案也是如此:

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

op = std::nullopt;

那么,您可能会问自己为什么会存在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
}

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

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

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

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

简而言之,std::nullopt可能很有用,但在您的情况下,它只是归结为样式。

匿名用户

std::nullopt解决了上面的缺点吗?

是的。

在某些上下文中,您可能希望有条件地返回一个脱离的可选对象(如果愿意,为空),而{}初始化语法不能明确地用于推导std::nullopt_t类型。 例如,当通过三元运算符表达式返回空的或非空的可选值时,如“返回可选值with?:运算符”中所述:

return it != map.end() ? std::make_optional(it->second) : std::nullopt;