为什么默认赋值运算符首先调用析构函数?

时间:2013-05-02 14:45:28

标签: c++

因此,在以下示例中,我们使类Foo将其替换为*this = Foo()。我很高兴我刚试过这个,因为在这种情况下,老Foo的析构函数不会被调用。我想这是因为默认赋值运算符只使用memcpy ...但是作为一个语言设计问题...为什么你不能让默认赋值运算符先破坏赋值的对象为了防止事故发生?

http://codepad.org/9WCo6yZ5

#include <iostream>
using namespace std;

class MustBeDestroyed //(for some reason not shown here)
{
public:
  int i;
  MustBeDestroyed(int i) : i(i) {}
  ~MustBeDestroyed() { cout << "destroyed contained class " << i << endl; }
};

class Foo
{
public:
  MustBeDestroyed x;
  Foo(int y) : x(y) {}
  void replace_myself(int y) { Foo f(y); *this=f; }
  void print() { cout << "This is outer/inner class " << x.i << endl; }
  ~Foo() { cout << "destroyed outer class " << x.i << endl; }
};

int main()
{
  Foo a(1);
  a.print();
  a.replace_myself(2);
  a.print();
  return 0;
}

2 个答案:

答案 0 :(得分:7)

因为首先破坏对象会终止生命。然后,您必须调用构造函数来启动新对象的生命周期。但是operator =的行为不是破坏当前对象并创建另一个对象,而是为现有对象分配一个新值。

基本上,你违反了3的规则。

答案 1 :(得分:2)

为什么赋值会调用析构函数?它完全按照它的说法执行:它调用赋值运算符。编译器生成的赋值运算符只是显而易见:将旧obejct中的所有成员分配给new(使用它们的赋值操作)。没有更多,没有更少。这正是着名的rule of three

的原因

现在它为什么不调用析构函数:这将结束对象的生命周期。虽然理论上可能构造一个新对象而不是旧对象,但在异常(look at this question for more about that)面前这种方法通常是不正确的,因此它不能用于一般情况。除非它采用你提出的方法,它不会为成员调用赋值运算符,而是调用析构函数/复制构造函数。这意味着不会遵守自定义分配行为(实际上不需要与复制行为相同)。