资源管理
读这章的时候发现之前对auto_ptr的理解有误,所以找了一些书重新看了一下智能指针模板相关的知识,先把这些基本知识附上。
auto_ptr是C++98中提出的,C++11中将其摒弃,同时提出了unique_ptr和shared_ptr。三者都定义了类似指针的对象,可以将new获得的地址赋值给对象,智能指针过期后,析构函数将使用delete释放内存,无需手动释放。
要创建智能指针,需包含头文件memory:
#include <memory>
using namespace std;
auto_ptr<int> pi(new int);
所有智能指针类都有explicit构造函数,不允许隐式类型转换:
shared_ptr<double> pd;
double *p_veg = new double;
pd = p_veg; // 不允许
pd = shared_ptr<double>(p_veg); //允许
注意:不要用非堆内存构造智能指针!!!
赋值上的区别:策略不同
1、所有权概念,对特定对象,只能有一个指针可以拥有它,赋值操作会转让所有权(auto_ptr和unique_ptr都是这样)
2、引用计数(shared_ptr是这样)
拷贝构造也是这样。
所有权转让后,原智能指针指向的为空,再次使用会有问题。
unique_ptr直接在编译阶段就禁止p1 = p2;这种赋值,不会等到运行时崩溃;
unique_ptr允许函数返回值的赋值,因为函数返回值是个临时对象,很快被销毁,即赋值右值是临时的,编译器允许。
unique_ptr<int> p1(new int);
unique_ptr<int> p2;
p2 = p1; //不允许
unique_ptr<int> p3;
p3 = unique_ptr<int>(new int); // 允许,临时对象转让后被销毁
容器对象建议不使用auto_ptr,可以使用unique_ptr,因为编译时有错误告警。
auto_ptr使用的是delete,不能用于数组,shared_ptr也不能用于数组。
unique有两个版本,所以可以用于数组。
条款13:以对象管理资源
获得资源后立刻放进管理对象内,资源取得时机便是初始化时机。
管理对象运用析构函数确保资源被释放。
auto_ptr和shared_ptr在复制行为上的区别
不可用于数组分配。
条款14:资源管理类中小心copying行为
策略:
1、禁止复制
2、对底层资源祭出引用计数法
3、复制底部资源,深度拷贝
4、转移底部资源的拥有权
复制RAII对象必须一并复制它所管理的资源,资源的复制行为决定了RAII对象的复制行为。
条款15:在资源管理类中提供对原始资源的访问
RAII不是为了封装,而是为了资源释放
对原始资源的访问可能经由显示转换或隐式转换,一般而言,显示转换比较安全,隐式转换比较方便
条款16:成对使用new和delete,要采取相同形式
new对应delete,new[ ]对应delete[ ]
条款17:以独立语句将new的对象置入智能指针
如果不这样,一旦发生异常,有可能导致难以察觉的资源泄露。
考虑如下代码:
processWidget( shared_ptr<Widget>( new Widget ), priority( ) ); //有问题
编译器中,参数入栈的顺序不固定。如果先new,再执行priority(),再讲资源放入shared_ptr,如果priority中出现异常,内存泄露。
应该如下处理:
shared_ptr<Widget> pw(new Widget);
processWidget( pw, priority( ) );