问题描述
第一种情况:
创建c++对象数组时候,如果通过初始化列表赋值,会产生临时变量,但为什么不会调用析构函数代码如下:
#include <iostream> using namespace std; class Point { public:Point():x(0),y(0){ cout<<'Default Constructor called.n';}Point(int xx,int yy):x(xx),y(yy){ cout<< 'Constructor called.n'; }~Point(){ cout<<'Destructor called.n'; }void Move(int xx,int yy) { x=xx; y=yy; } private:int x,y; }; int main() {Point A[2]={Point(1,2),Point()};cout<<'hello'<<endl;return 0; }
输出结果为:
其中,Point A[2]={Point(1,2),Point()};通过两个临时变量初始化对象数组A,之后为什么不会调用析构函数将其析构,结果中并未调用这两个临时对象的析构函数。
第二种情况:分别为数组的每个元素显示调用构造函数,就会自动调用析构函数:代码如下:
#include <iostream>using namespace std;class B{ int x, y;public: B(); B(int i); B(int i, int j); ~B(); void Print();};B::B() :x(0), y(0){ cout << 'Default constructor called.n';}B::B(int i) : x(i), y(0){ cout << 'Constructor 1 called.n';}B::B(int i, int j) : x(i), y(j){ cout << 'Constructor 2 called.n';}B::~B(){ cout << 'Destructor called.n';}void B::Print(){ cout << 'x=' << x << ', y=' << y << endl;}int main(){ B *p; p = new B[3]; cout << '*******' << endl; p[0] = B(); p[1] = B(7); p[2] = B(5, 9); for (int i = 0; i < 3; i++)p[i].Print(); cout << '*******' << endl; delete[]p;}
运行结果如下:
可见在为每个数组元素调用构造函数初始化后,临时变量析构了。
综上两种情况都是临时变量,但是为什么一个会自动析构,另一个不会,求解!!!
问题解答
回答1:重新查了一下资料,同时自己动手时实践了一下,更正错误原因:对象赋值是将右侧的对象的成员的值复制到左边的对象,然后释放右边的对象——————————每一次调用B()(有参或无参)都创建了一个临时对象情况一.创建临时对象(保存在A)后未被赋值,也就不存在释放右侧对象的过程,A中的对象存活至main()结束情况二.对p数组赋值,创建临时对象赋值给原来的对象,原来的对象(即初始化p时自动创建的临时对象)仅仅是被赋值,右侧的临时变量被析构,delete时析构p中保存的临时对象——————————至于为什么A中右侧的临时变量没有被析构,你可以试试在构造函数中输出一下this,然后再输出一下A中保存的对象的引用你就知道了,如果还有错误或不懂请指出,我会及时更正或解答
回答2:1.栈空间申请变量的生存期,在超出作用范围时销毁,这个作用范围在main函数。2.delete的不用多说。首先B[3]也是栈空间,但是你重新赋值后他的,使命就结束了,尽早回收。
回答3:Point A[2]={Point(1,2),Point()};
数组A是函数局部变量,内存分配在栈区,Point(1,2),Point()这两个也是局部变量,同样分配在栈区。这个时候编译器一般会做个优化,减少一次内存回收与分配。
p = new B[3];cout << '*******' << endl;p[0] = B();p[1] = B(7);p[2] = B(5, 9);
数组p内存空间是动态分配的,处于堆区。B(0),B(7),B(5, 9)三个是分配在栈区上的局部变量。双方内存分配位置不同,编译器也不可能做优化,只能老老实实地析构。