为什么引用类型成员会导致隐式声明的复制赋值运算符被删除

时间:2014-11-15 13:13:17

标签: c++

来自CPP Reference:

删除了隐式声明的复制赋值运算符 类T的隐式声明或默认的复制赋值运算符被定义为以下任何一种情况下删除:

T has a non-static data member that is const
T has a non-static data member of a reference type.
T has a non-static data member that cannot be copy-assigned (has deleted, inaccessible, or ambiguous copy assignment operator)
T has direct or virtual base class that cannot be copy-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
T has a user-declared move constructor
T has a user-declared move assignment operator 

那么告诉我是什么原因导致删除但不是为什么?任何人都可以解释:

T has a non-static data member of a reference type.

这是否足以让我的班级处理被删除的算子:

T& T:operator=(T& t){};

如果我有一个基类的成员,它是一个引用类型。

我是否需要在operator=中执行任何操作,例如显式声明return *this,或者编译器(g ++)是否会为我处理此问题?我是否必须与参考成员做一些特别的事情?很抱歉没有问题,但我是C ++的新手,已经开始使用托管语言(C#和Java)。

2 个答案:

答案 0 :(得分:14)

引用在初始化时绑定到对象,并且在此之后永远不会被更改,您对其执行的所有操作都会影响它们绑定的对象,而不是引用本身。

因此在构造期间设置了引用成员,并且从未更改过。由于赋值运算符的目的是在构造之后更改成员,因此在永远不能更改其中一个成员时生成隐式赋值运算符是没有意义的。编译器拒绝尝试猜测您希望它做什么,并强制您为自己的赋值运算符提供所需的语义。

  

我是否需要在运算符中执行任何操作=例如显式声明return * this或编译器(g ++)是否会为我处理此问题?

你绝对绝对需要return *this;

唯一一次你不需要在C ++中显式返回的是你的函数返回void还是main()(如果你到达结束时隐含return 0;函数)或在不常见的情况下,例如永不返回的函数(永远循环或抛出异常)。

  

我是否必须对参考成员做任何特别的事情?

这取决于您期望分配类型的语义。

如果你不想让它更改引用所绑定的对象,那么就可以了,不管它做什么。

如果你想要赋值来改变引用所绑定的对象,你需要这样做。

如果您希望将引用重新绑定到其他对象,那么您运气不好,C ++不允许这样做。

答案 1 :(得分:5)

无法更改参考。可以更改引用引用的对象,但引用本身不能更改。

考虑

struct A {
  int &r;
  A(int &r_) : r(r_) { }
};

int main() {
  int i, j;
  A a1(i), a2(j);
  a1 = a2;
}

您可以在任何自定义operator=实施中执行 nothing ,这会使a1.r引用j,这就是为什么没有operator=已创建或应代表您创建。

如果您的情况operator=可以不更改该引用,那么您可以定义自己的引用。

如果您有需要 operator=更改引用的情况,那么您的课程不应该使用引用。指针可能更合适。