当我们可以使用统一初始化轻松地默认构造std::optional
时?
std::optional<T> foo() {
if (on_error)
return {};
// ...
}
std::nullopt
解决了上面的缺点吗?
不。
这是一种非常有效的默认构造可选
的方法。
即使是分配,也可以使用={}
复制分配默认构造的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;