简体   繁体   English

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

[英]Why doesn't default assignment operator call the destructor first?

So in the following example, we cause class Foo to replace itself with *this = Foo() . 因此,在下面的示例中,我们使类Foo*this = Foo()替换自身。 I'm glad I just tested this because it turns out in this circumstance, the destructor of the old Foo doesn't get called. 我很高兴我只是测试了这个,因为事实证明,在这种情况下,旧Foo的析构函数不会被调用。 I guess that's because the default assignment operator just uses memcpy ... but as a language design question ... why wouldn't you make the default assignment operator destroy the assigned-to object first to prevent accidents? 我想这是因为默认赋值运算符只使用memcpy ...但是作为一个语言设计问题...为什么不让默认赋值运算符首先破坏已分配的对象以防止意外?

http://codepad.org/9WCo6yZ5 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;
}

Because destroying the object first would end the lifetime. 因为首先破坏对象会终止生命。 Then you would have to invoke a constructor to start the new object's lifetime. 然后,您必须调用构造函数来启动新对象的生命周期。 But the behavior of operator= isn't to destroy the current object and create another, but to assign a new value to the existing object. 但是operator =的行为不是要销毁当前对象并创建另一个对象,而是要为现有对象分配一个新值。

Basically, you violated the rule of 3. 基本上,你违反了3的规则。

Why would assignment call the destructor? 为什么赋值会调用析构函数? It does exactly what is says it does: It calls the assignment operator. 它完全按照它的说法执行:它调用赋值运算符。 The compiler generated assignment operator simply does the obvious: assignment of all members from the old obejct to the new (using their assignment operation). 编译器生成的赋值运算符只是显而易见:将旧obejct中的所有成员分配给new(使用它们的赋值操作)。 Nothing more, nothing less. 没有更多,没有更少。 This is exactly the reason for the famous rule of three . 这正是着名的三人统治的原因。

Now as to why it doesn't call the destructor: That would end the lifetime of the object. 现在它为什么不调用析构函数:这将结束对象的生命周期。 While it is theoretically possibly to construct a new object inplace of the old one, that approach is typically incorrect in the face of exception ( look at this question for more about that ), so it can't be used in the general case. 虽然理论上可能构造一个新对象而不是旧对象,但是在异常面前这种方法通常是不正确的( 关于这个问题,请查看这个问题 ),因此它不能用于一般情况。 Besides if it did the approach you proposed, it wouldn't call the assignment operators for the members, but destructor/copy constructor instead. 如果它采用你提出的方法,它不会为成员调用赋值运算符,而是调用析构函数/复制构造函数。 That means that custom assignment behaviour (which doesn't actually need to be the same as copy behaviour) would not be honored. 这意味着不会遵守自定义分配行为(实际上不需要与复制行为相同)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM