在C++中意外调用析构函数

Uts*_*sav 0 c++ oop destructor

请考虑以下部分代码.

#include<iostream>

using namespace std;

class A
{
private:
  int *x;
public:
  A(int a)
  {
    cout<<"creating "<<a<<" "<<this<<endl;
    x = new int;
    *x = a;
  }

  A(A *a)
  {
    this->x = a->x;
  }

  ~A()
  {
    cout<<"destroying "<<x<<endl;
    delete x;
  }

  A *operator+(A a)
  {
    return new A(*x + *(a.x));
  }

  void display()
  {
    cout<<*x<<endl;
  }
};

int main()
{
  A a(5);
  A b(10);
  A c = a + b;

  cout<<"control returns to main"<<endl;
  a.display();
  b.display();
  c.display();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

它产生以下输出.

creating 5 0xbffd6710
creating 10 0xbffd6714
creating 15 0x9273028
destroying 0x9273018
control returns to main
5
0
15
destroying 0x9273038
destroying 0x9273018
destroying 0x9273008
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么在将控件返回到main函数之前调用析构函数.更重要的是为什么要求它b?如果在它返回的新对象上调用operator+它将是可以理解的,因为当控件超出对象范围时调用析构函数.

小智 6

A *operator+(A a)
  {
Run Code Online (Sandbox Code Playgroud)

按价值收货.这意味着何时

a + b;
Run Code Online (Sandbox Code Playgroud)

遇到b创建并传递给 的新副本operator+(A a)

您没有看到构造一个新的,因为您没有实现复制构造函数,并且编译器为您创建了它.否则你会看到另外一个A被创建.

如果你改为operator*使用这样的参考

  A *operator+(A& a)
  {
    return new A(*x + *(a.x));
  }
Run Code Online (Sandbox Code Playgroud)

您不会再看到破坏,因为没有创建副本.