前言
SmartPtr技术经常被人误解为是一种GC手段。理论上它可以成为GC,但这只能够是一种“理论”而已。
我个人倾向于把SmartPtr理解为一种异常处理规范(Exception Handling Specification)。与异常处理相关,程序设计有一个基本原则:无论发生何种异常,应尽可能保证申请的资源(包括但不限于内存资源)被释放。
在资源申请、释放在一个局部过程中时,可以采用的方式有: try..catch 在申请一个资源那一刻开始,到资源释放的整个过程,使用try..catch将代码包含。以下是这个过程的标准写法:
MyClass* pObj = new MyClass; // 申请内存资源的开始
try { ... // 对该内存资源的正常处理过程 }
catch(...) { delete pObj; throw; // 将异常重新抛出 }
delete pObj;
使用资源句柄类将资源用类进行包装,由类进行资源的申请、释放操作。这种类我们称为资源句柄类(Resource Handle Class)。
在这种技术下,以上例子简化为很简单几句代码:
std::auto_ptr<MyClass> spObj(new MyClass); ... // 对该内存资源的正常处理过程
即使发生异常,C++编译器仍然可以保证,声明在栈中,并且已经被构造的自动变量在异常机制的“栈展开”过程中执行析构操作,从而保证了资源的释放。
释义
智能指针(SmartPtr)其实只是是资源句柄类(Resource Handle Class)中的一种。当一个资源句柄类管理的是内存资源时,我们称之为智能指针(SmartPtr)。从实现上来说,多数智能指针是带引用计数(Reference Count)的,如:boost::shared_ptr,ATL::CComPtr等。当然也有简单不带计数的,如STL的std::auto_ptr。
缺陷
我们推荐对所有的资源(而不单单是内存资源)使用资源句柄类。而相反,其实内存资源我们反倒不推荐使用资源句柄类。这句话的正确的理解是: 我们不推荐你用智能指针(SmartPtr),而是推荐用GC Allocator技术去解决内存管理问题。因为内存资源的使用环境过于复杂,已经远超出了简单的资源句柄类可以解决的范畴。