析构函数(Destructor)
先回顾一下构造函数
成员函数的一种
名字与类名相同
可以有参数,不能有返回值
可以有多个构造函数
用来初始化对象
析构函数
成员函数的一种
名字与类名相同
在前面加’~’
没有参数和返回值
一个类最多只有一个析构函数
对象消亡时à自动被调用
在对象消亡前做善后工作
释放分配的空间等
定义类的时候没有写析构函数,那么编译器会生成一个缺省析构函数
不涉及释放用户申请的内存释放等工作。
定义了析构函数,则编译器不生成缺省析构函数
class String{
private:
char*p;
public:
String(){
p= new char[10];
}
~String();
};
String::~String(){
delete[] p;
}
析构函数和数组
对象数组生命周期结束时
à对象数组的每个元素的析构函数都会被调用
#include <iostream>
using namespace std;
class Ctest{
public:
~Ctest(){cout<<"destructor called."<<endl;
}
};
int main(){
Ctestarray[2];
cout<<"EndMain"<<endl;
return0;
}
析构函数和运算符delete
delete运算符导致析构函数调用
Ctest *pTest;
pTest = new Ctest; //构造函数调用
delete pTest;//析构函数调用
pTest = new Ctest[3]; //构造函数调用3次
delete []pTest;
构造函数和析构函数调用时机的例题
class Demo{
intid;
public:
Demo(inti){
id= i;
cout<<”id=”<<id<<”Constructed”<<endl;
}
~Demo(){
cout<<”id =”<<id<<”Deconstructed”<<endl;
}
};
Demo d1(1);
void Func(){
staticDemo d2(2);
Demod3(3);
cout<<”Func”<<endl;
}
int main(){
Demod4(4);
d4= 6; //使用了类型转换构造函数
//因为这里要生成一个临时对象,所以调用构造函数,输出id=6 Constructed,然后当这个赋值结束以后,临时对象也要消亡了,所以调用了析构函数,输出id=6 Deconstructed.
cout<<”main”<<endl;
{Demod5(5);}
Func();
cout<<”mainends”<<endl;
return0;
}
id=1 Constructed
id=4 Constructed
id=6 Constructed
id=6 Deconstructed
main
id=5 Constructed
id=5 Deconstructed
id=2 Constructed
id=3 Constructed
Func
id=3 Deconstructed
main ends
id=6 Deconstructed
id=2 Deconstructed
id=1 Deconstructed
同时我们还可以看到,先被构造的对象会最后被杀死。这是C++一个重要的思想。
构造函数和析构函数在不同编译器中的表现:
个别调用情况不一致
编译器有bug
代码优化措施
前面讨论的是C++标准,而没有牵扯编译器的问题。