析构函数的调用解决思路

析构函数的调用
#include<iostream>
using namespace std;
class Complex
{
public:
Complex(float m=0.0,float n=0.0)
{
cout<<"constructor"<<endl;
real=m;
image=n;
}
float Getreal()
{
return real;
}
float Getimage()
{
return image;
}
Complex Add(Complex & a);
Complex Sub(Complex & a);
~Complex();
private:
float real;
float image;
};


Complex Complex::Add(Complex &a)
{
Complex temp;
temp.real=real+a.real;
temp.image=image+a.image;
cout << "Add temp destructed!" << endl;
return temp;
}

Complex Complex::Sub(Complex &a)
{
Complex temp;
temp.real=real-a.real;
temp.image=image-a.image;
cout << "Sub temp destructed!" << endl;
return temp;
}

Complex::~Complex()
{
cout<<"destructor"<<endl;
}
int main()
{
Complex a1(2.4,3.5);
Complex a2(2.0,1.0);
Complex a3,a4;

a3=a1.Add(a2);
cout << "a3 temp destructed!" << endl;
a4=a1.Sub(a2);
cout << "a4 temp destructed!" << endl;
cout<<"the real of a3 is"<<a3.Getreal()<<",the image of a3 is"<<a3.Getimage();
cout<<endl;
cout<<"the real of a4 is"<<a4.Getreal()<<",the image of a3 is"<<a4.Getimage();
cout<<endl;
return 0;
}
运行后,add temp destructed,sub temp destructed 各句下面输出两个destructor,按我理解,就只处理temp这个变量,应该调用一次析构就够了,怎么两个呢?

------解决方案--------------------
虽然在Complex Complex::Add(Complex &a)这个函数中,形参Complex &a是个引用,但是也会调用构造函数和析构函数的
------解决方案--------------------
return temp;
这个语句也会产生临时对象,所以还需要析构次
------解决方案--------------------
不同意1楼的看法。传递引用就是为了避免拷贝函数的调用。Complex &a中的引用a,它所引用的对象当然会调用构造函数和析构函数,但很明显这不会发生在Add或者Sub函数内部。如果俺说错了,请大家批评:)

我是这么看这个问题的:以Add函数为例:
C/C++ code

Complex Complex::Add(Complex &a)
{
    Complex temp;  // 会调用Complex的构造函数,创建temp对象
    temp.real=real+a.real;
    temp.image=image+a.image;
    cout << "Add temp destructed!" << endl;
    return temp;   // return时,会调用Complex的析构函数,以销毁temp对象(1次destructor)
                       // 同时,由于返回值类型是Complex,因此会调用Complex的拷贝构造函数,
                       // 以返回一个临时的Complex对象,一般临时对象只被使用一次,就会被析构,
                       // 这就是为什么会两次调用Complex的析构函数的原因。
}

// 如果你把Complex Complex::Add(Complex &a)改成Complex& Complex::Add(Complex &a),那么上面说的调
//用拷贝构造函数的动作就不会发生,因此对应的第二次Complex的析构函数的调用也就不会发生。即在这种
//情况下,析构函数只会被调用一次。

------解决方案--------------------
2楼正解
函数返回值为非引用类型的时候,会创建一个临时对象,还需要再析构
而返回值为引用类型的时候,就没有复制返回值,而是返回对象本身;
总结一下:用函数返回值初始化临时对象与用实参初始化形参的方法是一样的
------解决方案--------------------
两次析构的原因:
一个是temp局部对象在函数返回时析构,另一个是返回值临时对象的析构。



------解决方案--------------------
临时对象在执行完操作符运算后释放,比如赋值给a3后就释放,采用引用则可以阻止这种释放,不过一般不推荐这种用法。

比如执行Complex & a3 = a1.Add(a2),则临时对象就不会马上释放,它的生命周期就等于a3,因为有人引用它。
这个时候add操作就只执行一个析构函数。