移动赋值运算符上的异常说明符如何影响移动构造函数?

Lin*_*gxi 3 c++ exception language-lawyer noexcept c++14

我正在使用GCC 5.2和clang 3.6进行测试,两者都在C++ 14模式下,并且它们提供相同的输出.

对于以下代码

#include <iostream>
#include <type_traits>

struct S {
  // S& operator= (S&&) noexcept { return *this; }
};


int main() {
  std::cout << std::is_nothrow_move_constructible<S>::value
            << std::is_nothrow_move_assignable<S>::value;  
}
Run Code Online (Sandbox Code Playgroud)

11得到的结果.但是如果取消注释移动赋值运算符,则输出变为01.如何noexcept对移动赋值运算符的显式规范可能会影响移动构造函数的规范?

Cor*_*mer 7

通过定义移动赋值运算符,由于规则5,您禁用了移动构造函数.该类不是is_nothrow_move_constructible因为它根本不是可构造的,除非你定义它,否则构造函数不再可用.

§12.8复制和移动类对象

如果一个类的定义X不明确宣布一个移动构造函数,一个将被隐式声明为默认,当且仅当
- X没有一个用户声明的拷贝构造函数,
- X没有一个用户声明的拷贝赋值运算符,
- X做没有用户声明的移动赋值运算符,
- X没有用户声明的析构函数,并且
- 移动构造函数不会被隐式定义为已删除.

在没有用户定义的移动构造函数的情况下,两者都是隐式定义的,并遵循以下规范.

§15.4例外规范

隐式声明的特殊成员函数应具有异常规范.如果f是隐式声明的默认构造函数,复制构造函数,移动构造函数,析构函数,复制赋值运算符或移动赋值运算符,则其隐式异常规范指定type-id T当且仅当T函数的异常规范允许时才由f隐式定义调用; f如果它直接调用的任何函数允许所有异常,则允许所有异常,并且f如果它直接调用的每个函数都不允许异常,则不允许异常.


Tre*_*key 5

通过声明移动赋值,您已经丢失了隐式移动构造函数.
请参阅下面的完整图表.

在此输入图像描述

  • 好图表!谢谢你的链接.红色表示在C++ 11和转发中已弃用.它们尚未被删除,但它们可能是未来的标准.准则:不要依赖弃用的行为.如果显式声明了析构函数,复制构造函数或复制赋值中的任何一个,则显式声明复制构造函数和复制赋值. (2认同)