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

Move assignment operator not being implicitly declared

本文关键字:移动 赋值运算符 声明      更新时间:2023-10-16

这不编译

#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 没有用户声明的析构函数。

我错过了什么?

没有

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

相反:

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

这仍然是用户声明的复制赋值运算符,只是一个deleteD 运算符。 它阻止隐式生成复制构造函数、移动构造函数和移动赋值运算符。

delete的东西与它根本不存在是不一样的; 声明delete事物,但如果通过重载解析选择,它们将生成错误。

您可以=default移动赋值并构造特殊成员函数,如果希望它们存在,尽管您delete复制赋值。