Ale*_*104 10 c++ move-semantics noexcept
class C
{
public:
C(C&&) = default; // (1)
C& operator=(C&&) = default; // (1)
C(C&&) noexcept = default; // (2)
C& operator=(C&&) noexcept = default; // (2)
}
Run Code Online (Sandbox Code Playgroud)
据我所知,如果移动构造函数/赋值运算符是由用户隐式生成或显式默认的(1),编译器将noexcept根据类的所有成员是否noexcept为移动操作提供保证来决定是否应该使用这些特殊成员函数。但是,如果我想使用默认移动特殊成员并强制它们不noexcept考虑移动操作的底层成员异常保证,该怎么办?(1)和声明之间的编译器有什么区别吗(2)?
Ale*_*104 10
好吧,我在 Nico 的 Josuttis 书《C++ Move Semantics - The Complete Guide》中找到了答案:
\n\n\n当您有默认的特殊成员函数时,您可以显式指定\n与生成的保证不同的 noexcept 保证。例如\n:
\nRun Code Online (Sandbox Code Playgroud)\nclass C\n{\n ...\n public:\n C(const C&) noexcept = default; // guarantees not to throw (OK since C++20)\n C(C&&) noexcept(false) = default; // specifies that it might throw (OK since C++20)\n ...\n};\n在 C++20 之前,如果生成的 noexcept 条件与指定的 noexcept 条件相矛盾,则定义的函数将被删除。
\n
我问这个问题是因为我希望 STL 算法始终将移动语义应用于我的类,无论其成员的异常保证如何,并且我准备好处理std::abort出现问题的情况。但似乎在 C++ 20 之前,强制保证noexcept移动特殊成员函数的唯一方法是显式定义它们,即使您不需要自己的实现。事实证明,C++20 通过允许我们noexcept为默认的特殊成员函数指定保证来解决这个问题。当然,与任何其他noexcept函数一样,如果类的任何成员在移动操作期间抛出异常,std::abort如果为该类声明了移动构造函数/赋值运算符,则将调用该类,正如@Micha\noexcept所指出的那样xc3\xablRoy在评论部分。