分配操作员 - 自我分配

cpx*_*cpx 13 c++ assignment-operator

编译器是否为自我赋值生成了赋值操作符?

class T {

   int x;
public:
   T(int X = 0): x(X) {}
};

int main()
{
   T a(1);
   a = a;
}
Run Code Online (Sandbox Code Playgroud)

即使班级成员不是指针类型,我是否总是需要防止自我分配?

Joh*_*web 12

编译器是否为自我赋值生成了赋值操作符?

不,不是的.它仅执行成员方式的副本,其中每个成员都由其自己的赋值运算符(也可能是程序员声明的或编译器生成的)复制.

即使班级成员不是指针类型,我是否总是需要防止自我分配?

不,如果您的所有类属性(以及它们的属性)都是POD类型,则不会.

在编写自己的赋值运算符时,如果您希望在未来证明您的类,即使它们不包含任何指针,也可以检查自我赋值.还要考虑复制和交换习语.

  • 或者重申:未来的维护者总是能够搞砸了,担心他们可能做什么或不做什么都没有效果.您可以做的就是保持更新,有用的文档和编写清晰的代码. (3认同)
  • 如果所有成员(包括基类)都处理自己的任务,那么您无需执行任何操作.编译器将依次调用每个成员的操作符/构造函数来生成成员复制和赋值.这很好.有时人们相信自我指派测试是一种优化,但它也可能是一种悲观 - 为**所有**作业添加额外的检查.如果自我赋值非常常见,也许我们应该使用赋值来查看代码.:-) (3认同)
  • @Johnsyweb:添加不必要的自我分配检查也不能保证维护者能够做正确的事情,但更有可能让知道他们正在做什么的人感到困惑.例如:"不必要的"在这里很重要,因为即使不是绝对必要的,通常(罕见)自我分配的复制类型也会从检查中受益. (2认同)

Rob*_*obᵩ 5

这是一个很容易凭经验检查的方法:

#include <iostream>
struct A {
  void operator=(const A& rhs) {
    if(this==&rhs) std::cout << "Self-assigned\n";
  }
};

struct B {
  A a;
};

int main()
{
  B b;
  b = b;
}
Run Code Online (Sandbox Code Playgroud)