zoukankan      html  css  js  c++  java
  • 智能指针

    智能指针其实挺容易的。

    1. scoped_ptr<T>

    将指针自身的生命周期与对象绑定,“我死之日也是你亡之时”

     例如:

    #include "boost/smart_ptr.h"
    
    void Sample1_ScopedPtr()
    
      boost::scoped_ptr<CSample>
    
           samplePtr(new CSample);
    
      if (!samplePtr->Query() )
    
      // just some function...
    
        return;   
    
      samplePtr->Use();
    
     
    当我们使用例外的时候处理指针是特别烦人的事情(容易忘记销毁它)。使用scoped_ptr 指针就能够在函数结束的时候自动销毁它,因为这时scope_ptr也要完蛋了。

     2、 shared_ptr

    通过引用计数来管理对象的生命,引用计数听过好多遍了--对引用次数作个记录,但要关键要搞清楚的是这个“计数”是放在哪儿的?计数是在直接由对象原始指针创建shared_ptr时在堆上分配的;而通过拷贝构造或赋值得到的shared_ptr的计数则指向此计数了。这注定了两件事:

    1.不能有多个shared_ptr直接由原始指针创建而来 2.不能形成循环计数。

    再有一个重点是,从其语义上,要对对象的生命周期做出管理。如果语境中,不需要一个指针具有管理对象生命周期的语义,此时再使用shared_ptr有可能会违背以上两点。此时可考虑使用week_ptr

    void Sample2_Shared(){
    
      // (A) 创建Csample类的一个实例和一个引用。
    
      boost::shared_ptr<CSample> mySample(new CSample);
    
      printf("The Sample now has %i references\n", mySample.use_count()); // The Sample now has 1 references
    
      // (B) 付第二个指针给它。
    
      boost::shared_ptr<CSample> mySample2 = mySample; // 现在是两个引用指针。
    
      printf("The Sample now has %i references\n", mySample.use_count());
    
      // (C) 设置第一个指针为空。
    
      mySample.reset();
    
      printf("The Sample now has %i references\n", mySample2.use_count());  // 一个引用
    
      // 当mySample2离开作用域的时候,对象只有一个引用的时候自动被删除。

    一个误用的例子:

    class foo {
    public:
        typedef std::shared_ptr<foo> type_ptr;
        //blablabla....
     
        type_ptr what_are_you_want_to_do() {
            // 一堆不知道干嘛的代码后
            return type_ptr(this);
        }
    };
     
    int main() {
        foo::type_ptr p = foo::type_ptr(new foo());
        p->what_are_you_want_to_do();
        return 0;
    }

    此处 return type_ptr(this) 语义不需要对foo对象的生命周期管理,使用shared_ptr是不合理的。

    但也确实脑慢了就容易错啊。

     

    3、 使用weak_ptr跳出循环

    weak_ptr并不对对象的生命周期进行参与,它的座右铭是“我只看看,不说话”,对象活着就用,不存在就返回空指针。

    其原理是,不对引用计数作修改。

     4、 Intrusive_ptr——轻量级共享智能指针

    shared_ptr比普通指针提供了更完善的功能。有一个小小的代价,那就是一个共享指针比普通指针占用更多的空间,每一个对象都有一个共享指针,这个指针有引用计数器以便于释放。但对于大多数实际情况,这些都是可以忽略不计的。

    前面三个指针对对象没啥要求,但intrusive_ptr 则要对象本身已经有了一个对象引用计数器,也是“侵入”的来源。此时因为“计数”在对象内,下面这样就没啥问题了(与shared_ptr相比):

    p = new P()
    f = boost::intrusive_ptr<P>(p)
    g = boost::intrusive_ptr<P>(p)
     

    如果你要使用intrusive_ptr 指向类型T,那么你就需要定义两个函数:intrusive_ptr_add_ref 和intrusive_ptr_release。下面是一个简单的例子解释如何在自己的类中实现:

    #include "boost/intrusive_ptr.hpp"
    
    // forward declarations
    
    class CRefCounted;
    
    namespace boost
    
        void intrusive_ptr_add_ref(CRefCounted * p);
    
        void intrusive_ptr_release(CRefCounted * p);
    
    // My Class
    
    class CRefCounted
    
      private:
    
        long    references;
    
        friend void ::boost::intrusive_ptr_add_ref(CRefCounted * p);
    
        friend void ::boost::intrusive_ptr_release(CRefCounted * p);
    
      public:
    
        CRefCounted() : references(0) {}   // initialize references to 0
    
    // class specific addref/release implementation
    
    // the two function overloads must be in the boost namespace on most compilers:
    
    namespace boost
    
     inline void intrusive_ptr_add_ref(CRefCounted * p)
    
        // increment reference count of object *p
    
        ++(p->references);
    
     inline void intrusive_ptr_release(CRefCounted * p)
    
       // decrement reference count, and delete object when reference count reaches 0
    
       if (--(p->references) == 0)
    
         delete p;
    
    } // namespace boost
    
    
  • 相关阅读:
    英语词汇——day 1
    英语词汇——day 2
    PHP的流程控制语句(上)
    思维导图——四级词汇1
    PHP语句块中使用date()函数时需注意wampserver的设置
    (转)Linux服务器调优
    (转)linux服务器安全配置攻略
    mysql 创建[序列],功能类似于oracle的序列
    计算服务器最大并发量http协议请求以webSphere服务器为例考虑线程池
    Spring中ApplicationContextAware接口的说明
  • 原文地址:https://www.cnblogs.com/justin_s/p/2411405.html
Copyright © 2011-2022 走看看