码迷,mamicode.com
首页 > 编程语言 > 详细

C++:析构函数

时间:2017-08-29 23:02:17      阅读:306      评论:0      收藏:0      [点我收藏+]

标签:log   tom   生成   析构   功能   src   size   语句   amp   

一、什么是析构函数

析构函数是类中一种特殊的成员函数,但其功能和构造函数是相反的,当对象结束其生命周期时,系统会自动调用该对象的析构函数进行清理工作(如释放内存中分配给该对象的空间,关闭打开的文件等)。另外析构函数没有返回值,不需要参数,也不能被重载且一个类中有且只能有一个析构函数。但和构造函数相似,析构函数的函数名和类名相同,只不过需要在函数名向加上一个~

语法:~ 类名(){/*...析构函数体...*/}

特别注意:

? 如果用户没有显式地在类中定义析构函数,编译器会在类中生成一个默认的析构函数。且任何对象在被系统销毁时,都会调用该对象的析构函数。

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     Student(){
 7         cout<<"调用了默认构造函数"<<endl;
 8     }
 9     Student(string name,int age):Name(name),Age(age){}
10     Student(const Student& stu);//拷贝构造函数
11     Student& operator=(const Student& stu);//赋值函数
12     ~Student(){ //析构函数 
13         cout<<"调用了析构函数"<<endl;
14     } 
15 private:
16     string Name;
17     int Age;
18 }; 
19 int main(){
20     Student stu1;
21     return 0;
22 }

技术分享

 ? main函数中,析构函数的调用发生在语句“return 0;”之后

 

二、对象的析构顺序

先来看一个例子

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     Student(){
 7         cout<<"调用了默认构造函数"<<endl;
 8     }
 9     Student(string name,int age,int id):Name(name),Age(age),ID(id){
10         cout<<"创建对象ID号为"<<this->ID<<"的对象"<<endl;
11     }
12     Student(const Student& stu);//拷贝构造函数
13     Student& operator=(const Student& stu);//赋值函数
14     ~Student(){ //析构函数 
15         cout<<"析构对象ID号为"<<this->ID<<"的对象"<<endl; 
16     } 
17 private:
18     string Name;
19     int Age;
20     int ID;//对象的ID号 
21 }; 
22 int main(){
23     Student stu1("Tomwenxing",23,1);
24     Student stu2("Ellen",22,2);
25     Student stu3("Jack",21,3);
26     Student stu4("Dick",23,4);
27     cout<<"---------------分界线---------------------"<<endl;
28     return 0;
29 }

技术分享

由上例可知,对象创建完毕后会被存放在内存中的一个中,因此根据栈的“先进后出”的原则,最后被创建的对象由于最晚添加到栈中,故会被最先析构;而最早创建的对象由于位于栈底,故最后才会被析构。

 

三、为什么编写析构函数

在C++中,如果用户在自定义的类中没有编写析构函数,那么编译器会在类中自动生成一个默认的析构函数,但通常情况下编译器生成的默认析构函数的函数体为空,即该析构函数什么工作也不做,例如上例中的Student类,如果不手动定义该类的析构函数,那么系统默认生成的析构函数如下:

1 Student::~Student(){}//该析构函数什么工作也不做

有时候我们需要析构函数在销毁对象时完成一些清理工作。例如C++要求如果用new在内存中动态开辟了空间,则必须由相应的delete对该内存空间进行释放,因此如果我们自定义的类中含有指针成员变量,并在该类的构造函数中用new为该指针在内存中动态的分配空间,那么为了避免内存泄漏,就必须在该类的析构函数中使用delete来释放在内存中动态开辟的空间:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Example{
 5 public:
 6     Example()=default;
 7     Example(string message,int v):ptr(new string) ,ID(v){ //用new为指针ptr分配内存空间 
 8         *ptr=message; //将信息拷贝到动态分配的内存空间中 
 9         cout<<"创建对象ID为"<<this->ID<<"的对象"<<endl;
10     }
11     ~Example(){
12         cout<<"析构对象ID为"<<this->ID<<"的对象"<<endl; 
13         delete ptr;//释放ptr所指的内存空间 
14         ptr=NULL; //将指针ptr赋值为空 
15         cout<<"delete完毕!"<<endl; 
16     }
17 private:
18     string *ptr;//指针
19     int ID; 
20 };
21 
22 int main(){
23     Example example1("Tomwenxing",1);
24     Example example2("JackMa",2);
25     return 0; 
26 }

技术分享

再比如我们可以在构造函数中打开文件,而在析构函数中关闭文件;或在构造函数中打开和数据库的连接,而在析构函数中关闭和数据库的连接。等等......

因此简单来说就是在构造函数中获取系统资源,而在析构函数中释放这些系统资源以便这些系统资源被重新利用。

 

四、一个重要的原则——三法则(rule of three)

如果用户显示定义了类中析构函数、拷贝构造函数或赋值函数中的任何一个,那么另外两个函数通常也必须显式定义。

Question:什么时候需要显示定义?

Answer:当自定义类中有指针成员变量或需要利用某种系统资源时(如文件资源、数据库资源等)时,往往需要显示定义析构函数、拷贝构造函数和赋值函数。

 

C++:析构函数

标签:log   tom   生成   析构   功能   src   size   语句   amp   

原文地址:http://www.cnblogs.com/duwenxing/p/7450116.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!