17

尤其是在可能的情况std::vector下,类型noexcept可移动是很重要的。

所以当声明一个移动构造函数= default

struct Object1
{
    Object1(Object1 &&other) = default;
};

std::is_nothrow_move_constructible<Object1>::value将是true因为每个成员(此处为 0)Object1是 nothrow-move-constructible,此处已回答。

然而,如果只声明移动复制构造函数,然后= default像下面的代码那样定义,会发生什么?

struct Object2
{
    Object2(Object2 &&other);
};
Object2::Object2(Object2 &&other) = default;

使用 g++ 4.9.2 std::is_nothrow_move_constructible<Object2>::valuefalse我必须将声明和定义都标记为noexceptmake it true

现在我感兴趣的是实际规则是什么。特别是因为Effective Modern C++ (Scott Meyers) 中的第 22 项似乎通过建议实现 pimpl-idiom move 构造函数就像我对Object2.

4

1 回答 1

14

[dcl.fct.def.default]/p2:

如果一个函数在它的第一个声明中被明确默认,

  • 它被隐含地认为是constexpr隐含声明是否是,并且,
  • 它具有与隐式声明(15.4)相同的异常规范。

如果函数在以后的声明中显式默认,则这些规则不适用,就像在后面的示例中一样,因此,除了析构函数之外,noexcept(false)默认情况下会像大多数其他函数一样考虑该函数。

由于显式默认值可以在不同的翻译单元中 - 在 pimpl 的情况下,不同的 TU 中 - 编译器没有通用的方法来仅在查看类定义后确定移动构造函数是否会抛出,除非函数在类定义中显式默认(即,在其第一个声明处)。

于 2015-02-22T18:41:21.607 回答