c++析构函数

c++析构函数
首先我们来看一下有关析构函数的文字描述
1、定义
析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
2、 作用:对象消亡时,自动被调用,用来释放对象占用的空间
3、特点:
(1) 名字与类名相同
(2) 在前面需要加上"~"
(3) 无参数,无返回值
(4) 一个类最多只有一个析构函数
(5) 不显示定义析构函数会调用缺省析构函数

#include<iostream>
using namespace std;
class Test
{
    int id;
public:
	Test()
	{
	}
    Test(int i)
    {
        id = i;
    }
    ~Test()
    {
        cout<<"ID: "<<id<<" destruction function is invoked!"<<endl;
    };
};

int main()
{
    Test t0(0);                   //栈中分配   
	Test t1[3]={1,1,1};           //栈中分配 

    Test *t2 = new Test(2);       //堆中分配
    delete t2;

	Test *t3 = new Test[3]{3,3,3}; //堆中分配
    delete []t3;
    
    cout<<"------End of Main-------"<<endl;
    return 0;
}

在给出运行结果以前有必要说一下,我在vs2012的编译器里也运行了这段代码。但是其中Test *t3 = new Test[3]{3,3,3};这行代码是有错误的,我去查阅了相关的博客资料发现,在C++11中引进了这一新功能,即用new申请动态数组时可以直接初始化,形式如下:

int* p = new int[cnt]();  //其中cnt长度和int类型都可以自己定义。
int* p = new int[cnt]{ };

而且可以用这个方式给每个成员赋值。

int* a = new int[10] { 1,2,3,4,5,6,7,8,9,10 }; 

所以说上面的Test *t3 = new Test[3]{3,3,3};语句就应该是没问题的,下面给出运行结果。
在这里插入图片描述
解释:
在main函数中创建了t0,t1,t2,t3几个对象,这里先说一下C++创建对象的三种不同方式:

1、Test t0(0;                                    //栈中分配内存

2、Test t1[3]={1,1,1};          //栈中分配内存

3、Test *t2 = new Test(2);     //堆中分配内存

4、Test *t3 = new Test[3]{3,3,3};    //堆中分配内存

方法1、2中都是在栈中分配内存,在栈中内存由系统自动的去分配和释放,而使用new创建的指针对象是在堆中分配内存,当不需要该对象时,需要我们手动的去释放(delete),否则会造成内存泄漏。

在上述程序中,t0和t1都是栈中的对象,在程序结束时由系统来释放,因此出现在-----End of Main----之后。t2,t3是new出来的堆中对象,所以需要手动的delete释放,因此出现在最前面。另外有一点发现,就是栈中对象的释放顺序,是后定义的先释放,经过几次验证也如此,我想这恰好应征了栈的后进先出的特征。(先释放1,后释放0)

class Test
{
    int id;
public:
    Test(int i)
    {
        id = i;
    }
    ~Test()
    {
        cout<<"ID: "<<id<<" destruction function is invoked!"<<endl;
    };
};

Test t0(0);                        //最先创建的对象,最后释放

void Func()
{
    static Test t1(1);               
    //创建静态对象,会在整个程序结束时自动释放
    Test t2(2);             //在Func结束时自动释放
    cout<<"-----Func-----"<<endl;
}

int main()
{
    Test t3(3);
    t3 = 10;                         
    //类型转换构造函数,这里会创建临时对象,将int型转成Test类型对象,
    //在赋值结束后,临时变量销毁
    cout<<"------Begin of Main-------"<<endl;
    {
        Test t4(4);                 
         //花括号代表作用域,不需要等到main方法结束就释放了
    }
    Func();                          //进入Func函数
    cout<<"------End of Main-------"<<endl;
    return 0;
}

那让我们先分析一波 先是t3,t3创建完成以后想要把10赋值过来,但是一个是int类型,一个是Test,这里就会创建临时对象,将int型转成Test类型对象,在赋值结束后,临时变量销毁(把临时创建的对象得10赋值给了t3),销毁临时对象,调用一次析构函数,然后是------Begin of Main-------,到了t4,因为是在花括号里,直接调用了一次析构函数,不需要等到main方法结束,(此处如果没有花括号那么它应该在哪里呢,答案当然是在t3前面 也就是------End of Main-------之后的10前面),到了Func(); 里面的t1和t2,t1静态对象,会在整个程序结束时自动释放,t2在Func()结束时释放,所以先------Func------在调用析构函数,然后------End of Main-------,接着是释放t3,静态t1,最前面最先定义的t0;

在这里插入图片描述

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页

打赏作者

咋么又饿了

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值