为什么为具有引用成员变量的类生成默认的copy-ctor?

时间:2017-03-13 01:33:20

标签: c++ c++11

http://coliru.stacked-crooked.com/a/8356f09dff0c9308

#include <iostream>
struct A
{
  A(int& var) : r(var) {}
  int &r;
};

int main(int argc, char** argv)
{
    int x = 23;

    A a1(x);   // why this line is fine?

    A a2 = a1; // why this line is fine?

    a2 = a1; // error: use of deleted function 'A& A::operator=(const A&)'
            // note: 'A& A::operator=(const A&)' is implicitly deleted because the default definition would be ill-formed:
            // error: non-static reference member 'int& A::r', can't use default assignment operator
    return 0;
}

删除默认分配运算符。为什么仍然保留默认的拷贝构造函数?

3 个答案:

答案 0 :(得分:4)

A a1(x);

很好,因为它构建了一个A的实例,其引用(x被转换为引用,并且构造函数A(int&)被调用)

A a2 = a1;

也很好,因为它仍然是 构造。实际上是复制结构。 可以用另一个引用来初始化引用。

例如:

int a = 1;
int& b = a;
int& c = b;

没关系,因为这是所有构造(Demo

但是,您不能分配引用,这是a2 = a1将通过编译器生成的副本赋值运算符尝试执行的操作。但是,编译器认识到这一点并且没有生成这样的运算符。由于运算符不存在,因此出现编译错误。

答案 1 :(得分:0)

分配和构造是两种不同的野兽。

默认赋值运算符不能存在,因为无法将引用分配给(如果您尝试使用“user-land”代码,则实际上将分配给referant)。

默认的复制构造函数没有这样的问题,因为我们可以创建引用就好了。

答案 2 :(得分:0)

复制赋值运算符和复制构造函数是两个不同的东西。它不保证当复制赋值运算符存在时,复制构造函数也存在,但它们遵循自己的规则。

copy assignment operator,它提到:
如果T具有引用类型的非静态数据成员,则类T的默认复制赋值运算符被定义为“已删除”。那是这样的:D

对于Copy构造函数,它有自己的规则来决定是否删除,例如,如果类中存在非静态右值引用数据成员,则默认的复制构造函数将被定义为“已删除”。您可以访问docs了解更多信息。