请判断下述C++代码中noexcept表达式的条件定义是否正确?
逐个分析你代码里的noexcept标记是否正确:
接受
value_type const&的构造函数:noexcept(std::is_nothrow_copy_constructible_v<value_type>)是正确的。这个构造函数内部用传入的value拷贝初始化成员value_,只要value_type的拷贝构造不抛出异常,整个构造函数就不会抛异常,条件和实际行为完全匹配。接受
value_type&&的构造函数:
这里存在错误:代码里写的是value_{value},但value作为右值引用变量本身是左值,实际调用的是value_type的拷贝构造,而非移动构造。但你标记的noexcept(std::is_nothrow_move_constructible_v<value_type>)是针对移动构造的判断,和实际执行的操作不匹配——如果value_type的移动构造不抛但拷贝构造可能抛,这个构造函数就会违背noexcept的承诺。
正确写法应该是value_{std::move(value)},此时noexcept的条件才和实际执行的移动构造匹配,标记才正确。类的移动构造函数:
noexcept(std::is_nothrow_move_constructible_v<value_type>)是正确的。默认生成的移动构造函数会对成员value_执行移动构造,只要value_type的移动构造不抛,整个类的移动构造就不会抛,条件符合实际行为。类的移动赋值运算符:
noexcept(std::is_nothrow_move_assignable_v<value_type>)是正确的。默认生成的移动赋值运算符会对成员value_执行移动赋值,只要value_type的移动赋值不抛,整个类的移动赋值就不会抛,条件和实际操作一致。operator==和operator!=:
标记noexcept是合理的。你的value_type是std::string,它的比较运算符不会抛出异常,所以这两个运算符的noexcept承诺是成立的。
另外补充:operator()()没有标记noexcept是正确的,因为它返回value_的拷贝,而std::string的拷贝构造可能抛出异常,不能做出noexcept承诺。
内容的提问来源于stack exchange,提问作者Tippa Toppa

