当前位置: 代码迷 >> 综合 >> 第三章 资源管理
  详细解决方案

第三章 资源管理

热度:54   发布时间:2023-12-10 13:20:54.0

十三、以对象管理资源
这里用两个智能指针做示范
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被设置为NULL

引用计数型指针 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());

怎么调用processWidget(...)函数呢?
在processWidget (std::tr1::shared_ptr<Widget>(new Widget),priority())的过程中
有可能会导致资源泄漏,为什么?
考虑下两个参数,有两种调用顺序。
A、
<1>、调用priority
<2>、执行"new Widget"
<3>、调用tr1::shared_ptr构造函数
B、
<1>、执行"new Widget"
<2>、调用priority
<3>、调用tr1::shared_ptr构造函数

priority()有可能出现异常,在这种情况下,危险发生了。
因为new Widget返回的指针丢掉了,因为它没有被置入tr1::shared_ptr内,所以经过processWidget的
处理会导致资源泄漏
    面对这种问题,要有好的习惯
    shd::tr1::shared_ptr<Widget> pw(new Widget);
    processWidget(pw,ipriority());
   
总结:在一个独立的语句中将 new 出来的对象存入智能指针。如果疏忽了这一点,当异常发生时,可能引起微妙的资源泄漏