天天看点

第三章 资源管理

十三、以对象管理资源

这里用两个智能指针做示范

class Investment
 {
     Initialization* CreateInvetment(); // 
 }
 void f()
 {
     Initialization* pInv = CreateInvetment(); // 调用 factory函数
     ...
     delete pInv; // 释放pInv
 }      

上述代码中,在创建指针和删除指针之间,有可能会因为种种原因(比如后人维护代码过程中,执行了return语句),造成delete没有被执行

解决办法是以对象管理资源

void f()
 {
     std::auto_ptr<Initialization> pInv(CreateInvetment());
 }      

以对象管理资源的两个关键技术思想

1、获取到资源后立即放进管理对象

2、管理对象运用析构函数确保资源被释放

注意;受auto_ptr管理的资源必须绝对没有一个以上的auto_ptr同时指向它

举例:

std::auto_ptr<Initialization> pInv1(CreateInvetment());
 std::auto_ptr<Initialization> pInv2(pInv1); // pInv2 指向对象,pInv1被设置为NULL
 pInv1 = pInv2; // pInv1指向对象,pInv2被设置为NUL      

L

引用计数型指针 RCSP (reference-counting smart pointer),RSCP也是个智能指针,持续追踪共有多少个

对象指向某笔资源,并在无人访问它的时候自动删除该资源

void f()
 {
     std::tr1::shared_ptr<Initialization> pInv(CreateInvetment());
     std::shared_ptr<Initialization> pInv2(pInv1); // pInv1和pInv2指向同一对象
     pInv1 = pInv2; // pInv1和pInv2指向同一对象}      

总结:

1、为了防止资源泄漏请使用RALL对象,它们在构造函数中获得资源并在析构中释放资源

2、两个常备使用的RALL call是突然::shared_ptr 和auto_ptr。前者

十四、在资源管理类中小心Coping行为

RALL (Resource Acquisition is Initialization),适用于heap-based资源上

但是并非所有的资源都是heap-based,对于这类资源,auto_ptr和tr1::shared_ptr这样的只能指针往往不适合作为资源管理者

在这种情况下,需要建立自己的资源管理类

总结:

在自己的资源管理类中,如果不希望发生对象的复制行为,将设置复制函数为private

十五、对原始资源的访问

显示转换和隐式转换

隐式转换就是不带转换类型的转换,如int转float你可以这样子float a ;int b = 4;

a=b就是隐式转换,而a = (float)b就是显示转换

总结:

1、API 往往要求访问原始资源,所以每一个RALL类应该提供一个"取得其所管理资源"的办法

2、对原始资源的访问,可能经由显式转换或者隐式转换,一般而言显式转换更安全,但隐式转换对客户来说更方便

十六、承兑使用new和delete是要采取相同形式 

当你使用了一个 new 表达式(也就是说,通过使用 new 动态创建一个对象),有两件事情会发生。首先,分配内存

(通过一个被称为 operator new 的函数——参见 Item 49 和 51)。第二,一个或多个构造函数在这些内存上被调用。

当你使用一个 delete 表达式(也就是说,使用 delete),有另外的两件事情会发生:一个或多个析构函数在这些内存上被调用,

然后内存被回收

    new[]出来的对象,用delete释放,可能只释放了一部分,

    new出来的对象,用delete[]释放,可能将一块内存释放很多次

总结:

new\delete对应,和new[]\delete[] 对应

十七、在一个独立的语句中,将new出来的对象存入只能指针

"为什么要这么做?不这么做会怎样"

场景:

int priority();
     void processWidget(std::st1::shared_ptr<Widget> pw,int ipriority());      
A、
 <1>、调用priority
 <2>、执行"new Widget"
 <3>、调用tr1::shared_ptr构造函数
 B、
 <1>、执行"new Widget"
 <2>、调用priority
 <3>、调用tr1::shared_ptr构造函数      
shd::tr1::shared_ptr<Widget> pw(new Widget);
     processWidget(pw,ipriority());      

继续阅读