析构函数
波浪号加类名构成,没有返回值,也不接受参数
(由于不接受参数,因此它不能被重载)
作用
构造函数初始化对象的非static数据成员,析构函数释放对象所使用资源,并销毁对象的非static数据成员
执行顺序
构造函数中,成员初始化是在函数体执行之前完成的,且按照他们在类内出现的顺序进行初始化,析构函数中,首先执行函数体,然后销毁成员,成员按照初始化顺序的逆序销毁,所以析构函数可以执行设计者想要的任何收尾工作,再销毁成员
成员的销毁完全依赖于其本身的类型
成员的销毁完全依赖于其本身的类型,类类型需要执行自身的析构函数,而内置类型则什么也不做(无析构函数)
隐式销毁一个内置指针类型的成员不会delete它所指向的对象的原因
你觉得需要delete,那么这个指针必然是通过new构造的,但是事实上:
- 它可以指向一个栈上的地址
- 它可以指向别的类的成员
- 它可以与别的new构造的指针有alias
- 它可以是由new []或者malloc构造的…
这样的情况是不可能穷尽的,编译器也不可能记录下来具体是那种情况,并且分别采取对应的措施。
调用析构函数的情况:
1:变量离开作用域时被销毁
2:当对象被销毁,其成员被销毁
3:容器(无论是标准库容器还是数组)被销毁,成员被销毁
4:动态分配的对象,指针被delete时
5:临时对象(格式:类名()),创建的完整表达式结束时
class Sales_data
{
public:
Sales_data(const Sales_data&);
Sales_data();
Sales_data& operator=(const Sales_data&);
~Sales_data() { std::cout<<bookNo<<" delete" << std::endl; }
std::string bookNo;
int units_sold = 0;
double revenue = 0.0;
};
Sales_data::Sales_data(const Sales_data& orgig):bookNo(orgig.bookNo),units_sold(orgig.units_sold),revenue(orgig.revenue)
{
using namespace std;
cout << " copy Sales_data" << endl;
}
Sales_data::Sales_data()
{
using namespace std;
cout << " init Sales_data" << endl;
}
Sales_data* p = new Sales_data;
p->bookNo = "1";
auto p2 = std::make_shared<Sales_data>();
p2->bookNo = "2";
Sales_data item(*p); // 对象被销毁时,其成员被销毁
item.bookNo = "item p";
vector<Sales_data> vec;
vec.push_back(*p2); // 容器被销毁时,其元素被销毁
vec[0].bookNo = "vec p2";
delete p; // 动态分配的对象,指针被delete时
/*
退出局部作用域时,item,p2和vec调用析构函数
*/
输出结果
当指向对象的引用或指针离开作用域时,析构函数不会执行
class Sales_data
{
public:
Sales_data(const Sales_data&);
Sales_data();
Sales_data& operator=(const Sales_data&);
~Sales_data() { std::cout<<bookNo<<" delete" << std::endl; }
std::string bookNo;
int units_sold = 0;
double revenue = 0.0;
};
Sales_data::Sales_data(const Sales_data& orgig):bookNo(orgig.bookNo),units_sold(orgig.units_sold),revenue(orgig.revenue)
{
using namespace std;
cout << " copy Sales_data" << endl;
}
Sales_data::Sales_data()
{
using namespace std;
cout << " init Sales_data" << endl;
}
Sales_data sales_data;
sales_data.bookNo = "bookNo";
Sales_data& sales_data1 = sales_data;
Sales_data* sales_data2 = &sales_data;
//退出局部作用域时 ,sales_data 调用析构函数
//sales_data1和sales_data2不调用析构函数
输出结果:
析构函数体自身并不直接销毁成员
析构函数体自身并不直接销毁成员,成员是在析构函数体之后隐含的析构阶段中被销毁的。在整个对象销毁过程重视那个,析构函数体是作为成员销毁步骤之外的另一部分进行的。