2.2.3 抽象和内存管理
有些语言通过垃圾收集(garbage collection)来解决这个问题,这是一种当内存空间不再需要时自动回收内存的技术。垃圾收集使得编写程序时能更方便地采用灵活的数据结构,但要求系统在运行速度、编译器和运行时系统复杂度方面付出代价。另外,垃圾收集只回收内存,不管理其他资源。C++(www.cppentry.com)采用了另外一种更不同寻常的方法:如果某种数据结构需要动态分配资源,则数据结构的设计者可以在构造函数和析构函数中精确定义如何释放该结构所对应的资源。
这种机制不是总像垃圾收集那样灵活,但是在实践中,它与许多应用更接近。另外,与垃圾收集比起来它有一个明显的优势,就是对环境要求低得多:内存一旦不用了就会被释放,而不是等待垃圾收集机制发现之后才释放。
仅仅这些还不够,要想名正言顺地放弃自动垃圾收集,还应该有一些好的理由。但是构造函数和析构函数的概念在其他方面也有很好的意义。用抽象的眼光看待数据结构,它们中的许多都有关于初始化和终止的概念,而不是单纯地只有内存分配。例如,一个代表缓冲输出文件的数据结构必须体现一个思想,就是缓冲区必须在文件关闭前释放。这种约定总是在一些让人意想不到的细节地方出现,而由此产生的bug也总是非常隐蔽、难觅其踪。我曾经写过一个程序,整整3年后才发现里面隐藏了一个bug! 在C++(www.cppentry.com)中,缓冲输出文件类的定义必须包括一个释放该缓冲区的析构函数。这样就不容易犯错了。垃圾收集对此无能为力。
同理,C++(www.cppentry.com)的很多地方也都用到了抽象和接口。其间的关键就是要能够把问题分解为完全独立的小块。这些小块不是通过规则相互联系的,而是通过类定义和对成员函数和友元函数的调用联系起来的。不遵守规则,就会马上收到由编译器而不是由异常征兆的出错程序发出的诊断消息。