移动赋值运算符未被隐式声明

时间:2017-12-24 00:34:52

标签: c++ c++11

这不编译

#include <utility>

struct S {
  int x;

  S& operator=(const S& o) = delete;

  // Uncomment this to compile
  //S& operator=(S&& o) = default;
};

int main() {
  S s1, s2;

  s1.x = 0;
  s2.x = 101;

  // Following 2 lines do not compile
  s1 = std::move(s2);
  s1 = static_cast<S&&>(s2);

  return 0;
}

clang 3.8.1和g ++ 6.3.0都拒绝编译此代码段。

锵:

c.cc:19:6: error: overload resolution selected deleted operator '='
  s1 = std::move(s2);
  ~~ ^ ~~~~~~~~~~~~~
c.cc:6:6: note: candidate function has been explicitly deleted
  S& operator=(const S& o) = delete;

G ++:

c.cc: In function ‘int main()’:
c.cc:19:20: error: use of deleted function ‘S& S::operator=(const S&)’
   s1 = std::move(s2);
                    ^
c.cc:6:6: note: declared here
   S& operator=(const S& o) = delete;
      ^~~~~~~~

我理解=delete不允许复制赋值运算符参与重载解析,但为什么会导致删除隐式声明的移动赋值运算符?

C ++标准说(12.8 / 9):

如果类X的定义没有显式声明一个移动构造函数,那么只有在以下情况下才会将其隐式声明为默认值:

  • X没有用户声明的复制构造函数,
  • X没有用户声明的复制赋值运算符
  • X没有用户声明的移动赋值运算符和
  • X没有用户声明的析构函数。

我错过了什么?

1 个答案:

答案 0 :(得分:7)

  

没有用户声明的复制赋值运算符

恰恰相反:

keyboardInput

这仍然是用户声明的复制赋值运算符,只是S& operator=(const S& o) = delete; d的运算符。它会阻止复制构造函数,移动构造函数并隐式生成赋值运算符。

delete d的东西与根本不存在的东西不同; delete声明了事物,但如果通过重载解析选择它们,则会产生错误。

您可以delete移动分配并构建特殊成员函数,如果您希望它们存在,尽管您进行了=default d副本分配。