为啥定义了移动构造函数而隐式删除了赋值运算符?

Posted

技术标签:

【中文标题】为啥定义了移动构造函数而隐式删除了赋值运算符?【英文标题】:Why is the move constructor defined and the assignment operator implicitly deleted?为什么定义了移动构造函数而隐式删除了赋值运算符? 【发布时间】:2017-05-13 15:25:56 【问题描述】:
struct Foo

    Foo() = default;
    Foo(Foo&&) = default;
;

int main()

    Foo a, b;
    a = b;
   // ^ 

   return 0;

错误:使用已删除的函数 'Foo& Foo::operator=(const Foo&)'

在 g++4.6 -std=c++0x 中没关系。 但是,在 g++6.2 -std=c++11 中是错误的。 为什么?

【问题讨论】:

进一步阅读:"注意:'constexpr Foo& Foo::operator=(const Foo&)' 被隐式声明为已删除,因为 'Foo' 声明了移动构造函数或移动赋值运算符”。那是因为标准是这样说的:***.com/questions/11255027/… 【参考方案1】:

答案是因为 C++ 标准是这么说的:

[class.copy]

如果类定义没有显式声明一个副本 构造函数,一个是隐式声明的。如果类定义 声明一个移动构造函数或移动赋值运算符, 隐式声明的复制构造函数被定义为已删除;除此以外, 它被定义为默认值(8.4)。

在你的情况下,你总是可以声明一个默认的复制构造函数:

 Foo(const Foo&) = default;

【讨论】:

【参考方案2】:

Sam 解释了为什么 GCC 6.2 的行为是正确的。

GCC 4.6 的行为仅仅是由于该版本中不完整的 C++11 支持(正如“实验性”C++0x 开关所证明的那样);直到 4.8 才完全支持 C++11。

【讨论】:

以上是关于为啥定义了移动构造函数而隐式删除了赋值运算符?的主要内容,如果未能解决你的问题,请参考以下文章

隐式移动构造函数和赋值运算符

派生类在基类中删除时是不是会有隐式复制构造函数或赋值运算符?

对象的赋值运算符

C++Primer 第十三章

基本语言

C++ 拷贝构造函数和赋值运算符