默认定义的移动构造函数的 noexcept 规则是什么?
What are the rules for noexcept on default defined move constructors?
特别是与 std::vector
相关时,重要的是类型在可能的情况下 noexcept
可移动。
所以当声明移动构造函数时 = default
如
struct Object1
{
Object1(Object1 &&other) = default;
};
std::is_nothrow_move_constructible<Object1>::value
将是 true
,因为 Object1
的每个成员(此处为 0)都不可抛出移动构造,答案是 here.
然而,如果仅声明移动复制构造函数然后 = default
像下面的代码那样定义会发生什么情况?
struct Object2
{
Object2(Object2 &&other);
};
Object2::Object2(Object2 &&other) = default;
对于 g++ 4.9.2 std::is_nothrow_move_constructible<Object2>::value
是 false
我必须将声明和定义都标记为 noexcept
以使其成为 true
.
现在我感兴趣的是实际规则是什么。
特别是因为 Effective Modern C++ 中的第 22 项(Scott Meyers)似乎给出了错误的建议,建议像我对 Object2
.
那样实现 pimpl-idiom 移动构造函数
[dcl.fct.def.default]/p2:
If a function is explicitly defaulted on its first declaration,
- it is implicitly considered to be
constexpr
if the implicit declaration would be, and,
- it has the same exception specification as if it had been implicitly declared (15.4).
如果函数在后面的声明中明确默认,则这些规则不适用,如在您后面的示例中,因此,除了析构函数之外,默认情况下该函数被视为 noexcept(false)
与大多数其他函数一样。
由于显式默认设置可以在不同的翻译单元中——在 pimpl 的情况下,是在不同的 TU 中——编译器没有通用的方法来确定之后仅查看 class 定义移动构造函数是否会抛出,除非该函数在 class 定义中明确默认(即在其第一个声明中)。
特别是与 std::vector
相关时,重要的是类型在可能的情况下 noexcept
可移动。
所以当声明移动构造函数时 = default
如
struct Object1
{
Object1(Object1 &&other) = default;
};
std::is_nothrow_move_constructible<Object1>::value
将是 true
,因为 Object1
的每个成员(此处为 0)都不可抛出移动构造,答案是 here.
然而,如果仅声明移动复制构造函数然后 = default
像下面的代码那样定义会发生什么情况?
struct Object2
{
Object2(Object2 &&other);
};
Object2::Object2(Object2 &&other) = default;
对于 g++ 4.9.2 std::is_nothrow_move_constructible<Object2>::value
是 false
我必须将声明和定义都标记为 noexcept
以使其成为 true
.
现在我感兴趣的是实际规则是什么。
特别是因为 Effective Modern C++ 中的第 22 项(Scott Meyers)似乎给出了错误的建议,建议像我对 Object2
.
[dcl.fct.def.default]/p2:
If a function is explicitly defaulted on its first declaration,
- it is implicitly considered to be
constexpr
if the implicit declaration would be, and,- it has the same exception specification as if it had been implicitly declared (15.4).
如果函数在后面的声明中明确默认,则这些规则不适用,如在您后面的示例中,因此,除了析构函数之外,默认情况下该函数被视为 noexcept(false)
与大多数其他函数一样。
由于显式默认设置可以在不同的翻译单元中——在 pimpl 的情况下,是在不同的 TU 中——编译器没有通用的方法来确定之后仅查看 class 定义移动构造函数是否会抛出,除非该函数在 class 定义中明确默认(即在其第一个声明中)。