搜索

首页  >  问答  >  正文

visual-studio - 关于c++对象数组初始化时产生的临时变量析构问题?

第一种情况:

创建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;
}



运行结果如下:


可见在为每个数组元素调用构造函数初始化后,临时变量析构了。


综上两种情况都是临时变量,但是为什么一个会自动析构,另一个不会,求解!!!

PHP中文网PHP中文网2738 天前1028

全部回复(3)我来回复

  • 黄舟

    黄舟2017-05-16 13:26:00

    重新查了一下资料,同时自己动手时实践了一下,更正错误
    原因:对象赋值是将右侧的对象的成员的值复制到左边的对象,然后释放右边的对象
    ——————————
    每一次调用B()(有参或无参)都创建了一个临时对象
    情况一.创建临时对象(保存在A)后未被赋值,也就不存在释放右侧对象的过程,A中的对象存活至main()结束
    情况二.对p数组赋值,创建临时对象赋值给原来的对象,原来的对象(即初始化p时自动创建的临时对象)仅仅是被赋值,右侧的临时变量被析构,delete时析构p中保存的临时对象
    ——————————
    至于为什么A中右侧的临时变量没有被析构,你可以试试在构造函数中输出一下this,然后再输出一下A中保存的对象的引用你就知道了,如果还有错误或不懂请指出,我会及时更正或解答

    回复
    0
  • 高洛峰

    高洛峰2017-05-16 13:26:00

    1.栈空间申请变量的生存期,在超出作用范围时销毁,这个作用范围在main函数。
    2.delete的不用多说。首先B[3]也是栈空间,但是你重新赋值后他的,使命就结束了,尽早回收。

    回复
    0
  • 大家讲道理

    大家讲道理2017-05-16 13:26:00

    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)三个是分配在栈区上的局部变量。
    双方内存分配位置不同,编译器也不可能做优化,只能老老实实地析构。

    回复
    0
  • 取消回复