【问题标题】:Move assignment operator not being implicitly declared未隐式声明移动赋值运算符
【发布时间】:2017-12-24 00:34:51
【问题描述】:

这不会编译

#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 都拒绝编译这个 sn-p。

叮当声:

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 有一个用户声明的复制赋值运算符,因此没有隐式声明的移动构造函数。

标签: c++ c++11


【解决方案1】:

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

相反:

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

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

deleted 与它根本不存在是不一样的; deleted 事物已声明,但如果通过重载决议选择,它们会产生错误。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-13
    • 2019-04-12
    • 1970-01-01
    • 2020-09-06
    • 2017-11-21
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    相关资源
    最近更新 更多