练习13.9:
析构函数完成与构造函数相反的工作:释放对象使用的资源,销毁非静态数据成员。从语法上看,它是类的一个成员函数,名字是波浪号接类名,没有返回值,也不接受参数。
当一个类没有定义析构函数时,编译器会为它合成析构函数。
合成的析构函数体为空,但这并不意味着它什么也不做,当空函数体执行完后,非静态数据成员会被逐个销毁。也就是说,成员是在析构函数体之后隐含的析构阶段中进行销毁的。
练习13.10:
这两个类都没有定义析构函数,因此编译器会为它们合成析构函数。
对StrBlob,合成析构函数的空函数体执行完毕后,会进行隐含的析构阶段,销毁非静态数据成员data。这会调用shared_ptr的析构函数,将引用计数减1,引用计数变为0,会销毁共享的vector对象。
对StrBlobPtr,合成析构函数在隐含的析构阶段会销毁数据成员wptr和curr,销毁wptr会调用weak_ptr的析构函数,引用计数不变,而curr是内置类型,销毁它不会有特殊动作。
练习13.11:
~HasPtr()
{delete ps;
}
练习13.12:
这段代码中会发生三次析构函数调用:
1.函数结束时,局部变量item1的生命期结束,被销毁,Sales_data的析构函数被调用。
2.类似的,item2在函数结束时被销毁,Sales_data的析构函数被调用。
3.函数结束时,参数accum的生命期结束,被销毁,Sales_data的析构函数被调用。
在函数结束时,trans的生命期也结束了,但它是Sales_data的指针,并不是它指向的Sales_data对象的生命期结束(只有delete指针时,指向的动态对象的生命期才结束),所以不会引起析构函数的调用。
练习13.13:
#include <iostream>
#include <vector>using namespace std;struct X {X() {cout << "构造函数X()" << endl;}X(const X &) {cout << "拷贝构造函数X(const X&)" << endl;}X &operator=(const X &rhs) {cout << "拷贝赋值运算符 = (const X&)" << endl;return *this;}~X() {cout << "析构函数~X()" << endl;}
};void f1(X x) {}void f2(X &x) {}int main() {cout << "局部变量:" << endl;X x;cout << endl;cout << "非引用参数传递:" << endl;f1(x);cout << endl;cout << "引用参数传递:" << endl;f2(x);cout << endl;cout << "动态分配:" << endl;X *px = new X;cout << endl;cout << "添加到容器中:" << endl;vector<X>vx;vx.push_back(x);cout << endl;cout << "释放动态分配对象:" << endl;delete px;cout << endl;cout << "间接初始化和赋值:" << endl;X y = x;y = x;cout << endl;cout << "程序结束:" << endl;return 0;
}
程序结束时有三次析构函数的调用,分别对应x、y和vx的第一个元素。