zoukankan      html  css  js  c++  java
  • Effective C++ 条款13/14 以对象管理资源 || 在资源管理类中小心拷贝行为

    三、资源管理

          资源就是一旦你使用了它,将来不用的时候必须归还系统。C++中最常用的资源就是动态内存分配。其实,资源还有 文件描述符、互斥器、图形界面中的字形、画刷、数据库连接、socket等。

    1、        以对象管理资源

          void f()

    {

        investment *plv = createInvestment();

        //这里存在很多不定因素,可能造成下面语句无法执行,这就存在资源泄露的可能。

        delete plv;

    }

         这里我们把资源放进一个对象里面,然后依赖C++本身的对象里面的析构函数帮我们确保资源被释放。这里用到auto_ptr来解决。这是一个类指针对象,也就是所谓的智能指针。其析构函数自动调用delete。

        std::auto_ptr<Investment> pInv1(createInvestment()); //pInv1指向createInvestment()返回物;
         std::auto_ptr<Investment> pInv2(pInv1);                      //现在pInv2指向对象,而pInv1被设为NULL;
         pInv1 = pInv2;                                                               //现在pInv1指向对象,而pIn2被设为NULL;

         还有一个问题就是,不能让多个auto_ptr同时指向某一个对象。auto_ptr还有一个特性就是,通过复制之后,其raw 对象被置为null。

         所以,我们引用一个  引用计数型智能指针  shared_ptr 。它可以持续跟踪共有多少个对象指向某笔资源,并在无人指向它是自动删除该资源。

        void f()

    {

        std::   shared_ptr<investment> plv1(createinvestment());//pInv1指向createInvestment()返回物;

        std::   shared_ptr<investment> plv2(plv1);//pInv1,pInv2指向同一个对象;

        plv1 = plv2;//同上,无变化

    }//函数退出,pInv1,pInv2被销毁,它们所指的对象也竟被自动释放。

       还有一个问题就是,上面两个智能指针 auto_ptr 与 shared_ptr在析构函数内只执行 delete 而不是delete[] ,也就意味着,在动态分配的数组上这两个指针也存在风险。这个可能就需要使用boost::   shared_array来帮助了。

    记住:

          为防止资源泄露,请使用RAII对象,他们在构造函数中获得资源,在析构函数中释放资源。

          两个比较常用的RAII类分别是auto_ptr和shared_ptr.后者通常都是较佳选择,因为其拷贝比较直观。

    2、    在资源管理类中小心拷贝行为

           在堆上申请的资源我们可以用上面的智能指针类去管理,但有些并不适合。这时,我们就需要建立自己的资源管理类。

      void lock(Mutex *pm);     //锁定pm所指的互斥量
      void unlock(Mutex *pm);        //将pm解除锁定
      //   我们建立的资源管理类可能会是这样:
         class Lock 
        {
            public: 
            explicit Lock(Mutex *pm)
            : mutexPtr(pm) 
            {
                 lock(mutexPtr); 
            } 
            ~Lock() 
            { 
                 unlock(mutexPtr); 
            } 
            private: 
            Mutex *mutexPtr; 
        }; 

       当Lock对象被复制,会发生什么?

    通常,我们会选择以下两种解决方案:

    1、禁止复制

    2、对底层资源使用  引用计数法

    通常只要内含一个tr1::shared_ptr成员变量,RAII类便可实现”引用计数“行为。
         class Lock
        {
            public:
                explicit Lock(Mutex *pm)
                : mutexPtr(pm, unlock)        //由于tr1::shared_ptr缺省行为是”当引用计数为0时删除其所指物“,幸运的是                                                          //我们可以指定”引用计数“为9时被调用的所谓”删除器“,即第二个参数unlock
            {
                lock(mutexPtr.get());
            }
            private:
    std::tr1::shared_ptr<Mutex> mutexPtr;
         };
         本例中,并没说明析构函数,因为没有必要。编译器为我们生成的析构函数会自动调用其non-static成员变量(mutexPtr)的析构函数。而mutexPtr的析构函数会在互斥量”引用计数“为0时自动调用tr1::shared_ptr的删除器(unlock)。
        Copying函有可能被编译器自动创建出来,因此除非编译器所生成版本做了你想要做的事,否则你得自己编写它们。

        记住:

    • 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为。
    • 普遍而常见的RAII类拷贝行为是:抑制拷贝,施行引用计数法。不过其它行为也可能被实现。 
  • 相关阅读:
    jenkins代理设置
    通过jenkins api 触发远程构建
    python小技巧-统计列表中每个元素的个数
    python列表反转
    python 黑板课爬虫闯关-第三关
    python 黑板课爬虫闯关-第二关
    python 黑板课爬虫闯关-第一关
    python 黑板课爬虫闯关-第五关
    爬虫-识别图形验证码-tesserocr
    python 黑板课爬虫闯关-第四关
  • 原文地址:https://www.cnblogs.com/zhuxuekui/p/3924308.html
Copyright © 2011-2022 走看看