【C++】析构函数
在开辟空间时,需要构造函数来开辟空间,对应,作用域退出时也需要一个函数做“收尾”的工作,与构造函数对应——析构函数析构函数和构造函数作用相反,用于释放对象的内存空间如果程序员未写构造函数,那么系统也会提供一个默认的构造函数,同样,如果程序员未写析构函数,那么系统也会提供一个默认的析构函数,在当前对象退出时,自动调用,进行释放空间。
·
文章目录
目录
什么是析构函数?
在开辟空间时,需要构造函数来开辟空间,对应,作用域退出时也需要一个函数做“收尾”的工作,与构造函数对应——析构函数
析构函数和构造函数作用相反,用于释放对象的内存空间
如果程序员未写构造函数,那么系统也会提供一个默认的构造函数,同样,如果程序员未写析构函数,那么系统也会提供一个默认的析构函数,在当前对象退出时,自动调用,进行释放空间。
使用
- 写法:
- ~类名
- 析构函数无参,构造函数可以有多个参数。构造函数在构造时,值不一样就可以有多个参数进行传值,而析构函数无论带不带参数,都是将其空间释放,不需要带参数。
- 一个类有且只有一个析构函数
- 问:既然每个类都能提供一个默认的析构函数,而且析构函数只有一个,那为什么程序员需要写?
- 在下面进行解答(可根据目录快速定位)
什么时候进行调用析构函数?
- 先说结论:作用域即将消失时,进行调用构造函数
- 下面举例解释:
class A{ public: A(int i=4,int j=8):m_i(i),m_j(j) { cout<<"A"<<m_i<<" "<<m_j<<endl; } ~A() { cout<<"~A"<<m_i<<" "<<m_j<<endl; } private: int m_i; int m_j; } void main() { A a; cout<<"main"<<endl; }代码说明:
定义A类,类内定义A的构造函数,声明了两个变量:m_i,m_j
构造函数A内输出“A”
析构函数~A内输出“~A”,输出结果用于验证主函数内调用情况
在主函数内,定义A类的对象a,对象内内有数据成员:m_i,m_j
- 运行结果:
- 结果说明:
- 在该例题中,析构函数的调用顺序是:在a的作用域即将消失时,进行调用构造函数
构造与析构的顺序?
- 先说结论::在同一个作用域中,构造和析构的顺序相反,先构造的后析构
- 下面举例解释,修改上述代码:
void main() { A a(3,6); A b(2,7); cout<<"main"<<endl; }- 运行结果:
- 结果分析:
- 先构造a对象,在构造b
程序员为什么要写析构函数,什么时候写?
- 既然每个类都能提供一个默认的析构函数,而且析构函数只有一个,那为什么程序员还要写:
- 先说结论:当有指针作为数据成员时,就需要我们程序员自己写析构函数,将构造函数中new的空间释放掉。
下面用代码举例进行解释:
class Student { public: Student(int num=1001,char *name="baobao",char sex='f',int age=20);//含参的构造函数 void Print(); prvate: int m_num;//编号 char *m_name;//姓名 char m_sex;//性别 int m_age;//年龄 } //冒号语法进行初始化 Student::Student(int num,char* name,char sex,int age):m_num(num),m_name(name),m_sex(sex),m_age(age) //在public处声明时写了默认值,定义时就不用再写啦 { } void Student::Print() { cout<<m_num<<" "<<m_name<<" "<<m_sex<<" "<<m_age<<endl; } void main() { Student s(1001,"pangpang",'m',20); s.print(); }- 代码说明:
- 定义student学生类,类内声明了含参的构造函数
- 类外对构造函数进行声明
- 对对象属性进行输出
- 主函数内定义类的s对象并赋值然后调用输出函数
- 输出结果:
- 此时,输出了“pangpang”的名字。如果要对“pangpang”字符串进行修改的话,需要用指针去开辟空间存储内容该内容进行修改。将m_name指针指向name所指向的那个字符串常量的首地址,但是字符串并没有开辟空间,就不能修改,因此,只有通过给m_name指针开辟内存大小,然后再把值拷贝到该空间内就可以修改了,让指针存储值而不是指向。
m_name=new char[strlen(name)+1];//在堆上开辟空间 strcpy(m_name,name);- 该空间的开辟是由程序员在堆上进行开辟的,需要程序员自己释放(栈上的空间不需要),因此需要写个析构函数,将构造函数中new的空间释放掉。而类内默认的析构函数没办法释放堆上的空间,只能释放栈上的,因此必须程序员自己写一个。
~Student() { if(m_name!=NULL) { delete []m_name; m_name=NULL; } }
更多推荐




所有评论(0)