Effective c++ 学习笔记(item13)
利用对象管理资源
利用对象管理资源可以解决大部分潜在的资源泄露问题。
以下面的例子说明如何用对象管理资源,而且我们使用了一种特制的对象"智能指针"对象。
Investment* createInvestment();
createnvestment()是工厂模式的一种实现,每次调用他会生产一个资源块,并返回指向这个资源块的指针。这种实现要求调用者去释放资源。假如调用者用下面的方式来使用和释放该资源:
Investment * pinv = createInvestment();
....//using pinv
delete pinv;
这种使用方式用显示的delete实现资源释放。在delete语句前如果不小心发生了异常后者return,会导致资源泄露。现在的静态检查,对因为分支return语句导致的泄露是能够检查出来的,但是异常还不行。
利用智能指针管理资源,核心的本质是借用系统自动调用析构函数的机制
提倡的资源管理方法是,申请后立即交给资源管理对象如下:
std::auto_ptr<Investment> pinv(createInvestment());
...
在上面的代码中生成的资源指针立即交给了智能指针对象pinv。pinv的使用方法跟资源指针一样,不过增加了对象属性,当离开作用域的时候会触发智能指针的析构函数,而智能指针的析构函数里面会自动delete关联的资源。使用智能指针在把资源交给智能指针的时候,最好用下面代码的方式1而不是方式2
方式1:
std::auto_ptr<Investment> pinv(createInvestment());
方式2:
Investment* srcPointer = createInvestment();
std::auto_ptr<Investment> pinv(srcPointer);
方式2不好的地方是暴露了srcPointer,如果有人不小心在函数的末尾多此一举来一次delete srcPointer那就会导致重复delete。
智能指针的约束
- 不能有多个智能指针指向同一份资源。
Investment* srcPointer = createInvestment();
std::auto_ptr<Investment> pinv(srcPointer);
std::auto_ptr<Investment> pinv2(srcPointer);
向上述的代码就是错误的,因为离开了作用域,pinv的析构和pinv2的析构都会触发delete,那样相当于delete两次同一份资源。系统会错误。
那么智能指针之间的赋值操作是否会导致多个智能指针对象关联一份资源呢。 智能指针在设计上保证了这块的安全性, 看下面示例的注释就能明白了:
std::auto_ptr<Investment> pinv1(createInvestment());
std::auto_ptr<Investment> pinv2(pinv1); //此语句之后pinv2关联资源指针,而pinv1将关联NULL.
pinv1 = pinv2; //此语句之后,pinv1关联资源指针,pinv2被自动设置关联为NULL.
可见智能指针在赋值,拷贝构造上都做了保护,确保一个资源仅仅关联一个智能指针对象。因为智能指针内部有这样的自动操作,智能指针是不允许放到容器里面的。容器要求放到容器内的对象能够正常的拷贝赋值。 这个在引申章节中具体讨论。
- 智能指针内部自动调用的是delete,需要delete[]的场合不能用
类似下面的代码是有问题的:
std::auto_ptr<int> pint(new int[20]());
正确的做法是在c++中用vector和string取代数组。c++不鼓励array,array数组越界是个很头疼的问题。
网友评论