C++基础语法:析构函数

前言

      "打牢基础,万事不愁" .C++的基础语法的学习."学以致用,边学边用",编程是实践性很强的技术,在运用中理解,总结.

引入

        用一个简单的例子,分析析构函数的工作过程.以<C++ Prime Plus> 6th Edition(以下称"本书")内容做参考.

回顾类的默认函数

        类的默认函数及用途如下:

                 构造函数:给属性赋值

                复制构造函数:用已有对象初始化新对象,对象之间传递属性值

                赋值符:类似于复制构造函数,传递值.

                析构函数:删除对象属性

        既然是默认函数,表示可以重载.如果没有属性,构造函数没有重载必要;复制构造函数和赋值符重载前面已解读过,应用场景是深复制中处理静态数据,以及复制指针原有的数据.这里主要是说析构函数的重载.

回顾new和delete

        new的含义:在堆空间上开辟内存空间,返回指向该内存空间首地址的指针

        delete的含义:释放new所指向的内存空间

        new的格式:

       指针类型 指针名=new 数据类型[元素个数];   //生成n个元素的数组,返回指针 

       指针类型 指针名=new 数据类型;                     //指向单个元素,返回指针 

int *par=new int[5];       //par指向一个整型数组的指针
int *p=new int;            //p指向一个int类型变量

        可以在后面用{}加上该种数据类型的值

        指针类型 指针名=new 数据类型[元素个数]{值列表(用逗号分开)};   

       指针类型 指针名=new 数据类型{单个值};     

int *par=new int[5]{1,2,3,4,5};       //生成指向整型数组的指针并赋值
int *p=new int{3};                    //生成指向单个整型值3的指针
=============
int b=par[1];                         //par[1]值为2,间接访问数组
int c=*p;                             //*p的值为3,间接访问数据

             delete的格式:和new相对应,当new生成的指针指向数组,用[],否则不用

delete[] par;    //释放par指向的内存空间
delete p;        //释放p指向的内存空间

析构函数的重载

        下面用一个简单例子来说明:

#include<iostream>
using namespace std;

class Demo {                                        //Demo类
	int* pint;
public:
	Demo(int* d):pint(d){}
	~Demo() { delete pint; }						//析构函数,注释看效果
};

class OutDemo {                                    //OutDemo类
	Demo* demo;
public:
	OutDemo (Demo * d)  : demo(d) {}
	~OutDemo() { delete demo; }						//析构函数,注释看效果
};

        测试代码:

int main(void) {

	int* pval = new int{ 3 };						//new生成整型指针
	Demo* pd = new Demo(pval);						//new生成Demo对象,返回指针
	OutDemo* pod = new OutDemo(pd);					//new生成OutDemo对象,返回指针

	cout << "调用析构函数前的值为:" << *pval << endl;
	cout << "调用析构函数前的地址为:" << pval << endl;

	delete pod;										//释放内存

	cout << "调用析构函数后的值为:" << *pval << endl;
	cout << "调用析构函数后的地址为:" << pval << endl;

}

        说明:分别注释两个重载的析构函数,可以看出不同.下面分析

析构函数的调用过程

        1>使用默认析构函数.

        此时上面两个类中的析构函数应处于注释状态.当调用delete pod;时, 调用默认析构函数,

~OutDemo() {};	        //默认析构函数

        按照默认构造函数的定义,对象中属性被删除,即数据类型Demo*,变量demo的表示的值-----pd被删除,而pd指向的数据pval未删除.所以打印出来的结果*pval仍然等于3.

        2>使用重载析构函数

        此时上面两个类定义的析构函数应处于非注释状态.当调用delete pod;时,调用重载析构函数

~OutDemo() { delete demo; }  

        重载析构函数实际上有两个部分,一是调用默认析构函数,把对象中的属性pd删除(与上面一条相同)二调用delete demo;------他的含义是调用Demo的析构函数,此时对应语句是:

~Demo() { delete pint; }

        此时再重复上一种状况,一删除对象属性pval,二调用delete pint,释放整型指针pint指向的空间,删除其数据,所以打印*pval的结果已发生改变.

        有一个细节:当传递进去的指针不是new生成时,会报错,如把int* pval = new int{ 3 };改成

int a=3;
int *pval=&a;

        运行后产生异常. 说明new和delete需配合使用

析构函数的小结

        默认析构函数做了什么? 删除属性

        重载析构函数做了什么?一调用默认析构函数;二根据内容操作.

        重点:当调用"delete 对象指针名"时,执行析构函数 .如果是默认析构函数则只删除属性,如果重载了析构函数先删除属性,再执行其他内容.

        优点:只要是传入的指针((new生成),在析构函数上加上删除语句(如delete p;),释放内存空间.而对象和他包含的对象之间是各自独立的.如delete pod;释放了最初传入的整型指针pval

        应用场景:对内存空间要求比较高时,不然传对象引用就可以了.在笔者另一篇帖子里C++基础语法:复制构造函数,赋值构造函数及浅复制,深复制_复制构造和赋值-CSDN博客有介绍

更新

        前面讲的都是针对指针属性,如果复杂一点,属性是双重指针该如何解决呢?思路一样的,析构函数中delete后面那个是指针.双重指针通常是指针数组,所以应该遍历他,再用delete.


class Demo {                                        //Demo类
	int** ppint;
public:
	Demo(int** d):pint(d){}
	~Demo() {
//        for(int i=0;i<sizeof(ppint)/sizeof(int*);i++){    //这种方法求不出指针数组长度
          for(int i=0;i<length;i++){               //这里length可以硬编码,因为数组长度固定
            delete ppint[i];                       //ppint的长度也是固定的
        } 
    }						                        
};

  • 24
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jllws1

你的鼓励是我创作的动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值