析构函数是一个特定的由用户定义的成员函数,当该类的对象离开了他的域,或者delete表达式应用到一个类对象的指针上时,析构函数就会自动被调用。析构函数的名字是在类名前加上波浪线(~),它不返回任何值也没有任何参数。析构函数主要被用来放弃在类对象的构造函数或生命期中获得的资源,如互斥锁或删除由new分配的内存。析构函数也不局限在放弃资源上,一般地,析构函数可以执行“类的设计者希望在最后一次使用对象之后执行的任何操作”。
显式析构函数
在某些程序情况下,有必要显示地对一个特殊类对象调用析构函数,这常常发生在和定位new操作符结合。例如当写char *p=new char[sizeof Image]时,分配了一个大小为Image的内存,然后使用定位new:Image *ptr=new (p)Image("aabbcc")时,没有新的内存被分配,但是构造函数被应用到现有的存储区上。实际上,定位new操作符允许我们在一个特定的、预分配的内存地址上构造一个函数。如果我们希望在p这块内存位置操作另外一个图像时,我们可能需要这样Image *ptr=new (p)Image("ddeeff")。但是我们要释放aabbcc这个对象,如果调用delete ptr,那么相应的存储区也会被删除。这时就需要显式地调用Image的析构函数 ptr->~Image(),这样底层的存储区可以被后面的定位new操作符调用继续使用。
尽管p和ptr都指向了同一个堆存储区,但是对p调用delete操作符不会导致调用Image的析构函数。因为p的类型是char*,只有当delete表达式中的指针指向一个带有析构函数的类类型时,编译器才会调用析构函数。
可能的代码膨胀
内联的析构函数可能是程序代码膨胀的一个源泉,因为他被插入到函数中的每个退出点,以析构每一个活动的局部类对象。解决方法是:或者把析构函数写成非inline的,或者改写程序结构。