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

Lut*_*rvd 17 c++

CPP参考:

已删除隐式声明的复制赋值运算符类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 
Run Code Online (Sandbox Code Playgroud)

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

T has a non-static data member of a reference type.
Run Code Online (Sandbox Code Playgroud)

以及这是否足以让我的班级处理已删除的运算符:

T& T:operator=(T& t){};
Run Code Online (Sandbox Code Playgroud)

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

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

Jon*_*ely 17

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

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

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

绝对绝对是100%需要的 return *this;

你不需要在C++中显式返回的唯一时间是你的函数返回void或者在main()(return 0;如果你到达函数的末尾有隐含的地方)或者在不常见的情况下,例如永远不会返回的函数(永远循环或抛出异常).

我是否必须与参考成员做一些特别的事情?

它取决于您期望分配类型的语义.

如果您不希望它更改引用绑定的对象,那么就可以执行任何操作.

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

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


小智 5

参考不能改变.可以更改引用引用的对象,但引用本身不能更改.

考虑

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

int main() {
  int i, j;
  A a1(i), a2(j);
  a1 = a2;
}
Run Code Online (Sandbox Code Playgroud)

没有什么你可以在任何自定义可能做operator=的实施,将使a1.rj,这就是为什么没有operator=被创建或应以您的名义创建.

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

如果您需要 operator=更改引用,则您的类不应使用引用.指针可能更合适.

  • 可怜的编译器。它与这个问题无关,但它一直在为它没有发言权的事情提供支持。 (3认同)
  • `operator=` 的复制赋值重载*总是* 声明的,无论是隐式还是显式。它可能会也可能不会最终被定义为已删除。 (2认同)