析构函数
析构函数与构造函数功能相反,构造函数在对象被创建后调用,用于对对象的初始化,而析构函数在对象被销毁时调用,用于对对象内成员所占用的空间进行回收。
析构函数名称与类名相同,前方有一个“~”,没有返回值,没有参数(这一点与构造函数不同)。一个类只有一个析构函数。
如果定义类时没有编写析构函数,编译器会生成默认析构函数。如果程序员定义了一个析构函数,编译器不会再生成析构函数。
为了确保对象所占用的空间被回收,析构函数在对象声明期结束时会被自动调用(析构函数调用时机的原因:无须每次对对象操作后进行回收,只要能保证对象最后一定会被回收就行)。一般在析构函数体内编写delete语句对对象的成员在运行期间开辟的空间的回收(与new对应)。
class MyString
{
char *buffer_;
public:
MyString(char num) :buffer_(new char[num]) {}
~MyString()
{
cout << "析构函数执行了!" << endl;
delete[] buffer_;
}
};
string Test()
{
cout << "Test()开始执行!"<<endl;
MyString first_string(2);
return "Test()执行结束!\n";
}
int main()
{
cout<<Test()<<endl;
system("pause");
return 0;
}
结果如下:
从输出中可以看到当Test()函数退出时,调用了析构函数来回收对象开辟的空间。
变量的生存期
对象何时生成和消亡是由对象的生存期决定的。
#include <iostream>
#include <string>
using namespace std;
class MyString
{
string buffer_;
public:
MyString(string init) :buffer_(init)
{
cout << "buffer_为" << buffer_ << "的构造函数执行了!" << endl;
}
~MyString()
{
cout << "buffer_为" << buffer_ << "的析构函数执行了!" << endl;
}
};
MyString g_first_string("dong");
string Test()
{
cout << "Test()执行了!" << endl;
static MyString second_string("nan");
MyString third_string3("xi");
return "Test()结束了!";
}
int main()
{
cout << "main()开始!" << endl;
MyString fourth_string("bei");
{
MyString fifth_string("zhong");
}
cout << Test() << endl;
return 0;
}
结果如下:
在main函数执行之前,全局对象就会被初始化(同时调用自己的构造函数,第一行就是调用时的输出)。
然后开始执行main函数内第一个局部对象buffer为“bei”的构造函数。
进入块作用域后执行局部对象“zhong”的构造函数。退出块作用域后调用"zhong"的析构函数。
然后开始执行Test函数。首先开始执行静态局部对象“nan”的构造函数(静态局部变量在程序执行到该对象的声明处时被初始化,调用自己的构造函数,它的作用域为局部,但生命期为全局,在main函数结束时调用自己的析构函数),然后开始执行局部对象“xi”的构造函数,函数执行结束时调用“xi”的析构函数。然后返回main函数。
在main函数退出后,全局对象、静态局部对象以及main函数内的局部对象的析构函数会被调用(在“Test()结束了”到最后一行之间都是析构函数被调用时的输出,其中全局对象是在局部对象和静态局部对象全部析构后才调用自己的析构函数,它最先出生最后死)。
参考
The C++ Programming Language (美) Bjarne Stroustrup
Thinking in C++ Volume One:Introduction toStandard C++ (美)Bruce Eckel
新标准C++程序设计教程 郭炜
cpp参考:https://zh.cppreference.com