C++11中的智能指针与C++98的智能指针设计对比

C++11中的智能指针与C++98的智能指针设计对比

众所周知,C++11更新了一个重要的feature,那就是智能指针类,由unique_ptr、shared_prt、weak_ptr组成,这为苦逼的C++程序员们带来了不小的好处:终于在某些情况下不用手动管理内存啦!和内存泄漏说拜拜!咦?为什么要说有些情况下呢?因为这智能指针,只是用了引用计数来实现内存的自动管理,而不像java、go语言那么智能,有gc线程进行处理。但总好过没有吧!起码有了智能指针,就会有C++的RAII思想。
但我作为一个嵌入式开发者,很多环境下还在用该死的GCC4.3、4.4编译器,由于C++11的特性得GCC4.6之后才支持,所以无法享受到智能指针的好处。不过没关系,由于C++的开放性,我们便自己创造了引用计数的智能指针,虽然以后必然会被C++11的智能指针所替代,但可以参考一下两者设计上的区别。
先看C++11 std::shared_ptr实现的原理:
shared_ptr中包含int *cnt和void *ptr两个成员变量,其中cnt为引用计数。可以发现这样的好处是,可以在不修改之前写的类,便可以使用智能指针,如:

  class my_class
  {
  public:
      my_class(int a)_a(a) {}
      virtual ~my_class() 
      {
          printf("my class destruct\n");
      }
      void print()
      {
          printf("value:%d\n", _a);
      }
  private:
      int _a;
  }

  int main(int argc, char **argv)
  {
      std::shared_prt<my_class> my = std::make_shared<my_class>(123);
      my->print();
  }

但这么使用有如下几个缺陷:
1、该指针只可使用一个shared_ptr来管理,否则可能出现多次析构的问题;
2、尽量不要使用shared_ptr的get方法获取裸指针;
3、在my_class中需要将this指针传出去,则得继承std::enable_shared_from_this,再使用shared_from_this()方法将this指针包裹后传出去。
以上的几点缺陷,都是因为引用计数是放在shared_ptr类中进行处理与计算,而不是在被管理的类中,所以在使用时,必须要对shared_ptr类进行拷贝处理。

而在我们设计的C++98模式里的智能指针,有一个基类:

class i_ref
{
public:
    virtual ~i_ref(){};
    /**
     * 增加引用
     */
    virtual unsigned long add_ref() = 0;
    /**
     * 释放引用
     */
    virtual unsigned long release_ref()= 0;
};

class c_ref
{
public:
    virtual ~c_ref(){};
    c_ref ()
        : m_lRef(0),m_lDel(1)   
    {
    }
    virtual unsigned long add_ref()
    {
        return InterlockedIncrement(&m_lRef);
    }
    virtual unsigned long release_ref()
    {
        if(InterlockedDecrement(&m_lRef) == 0  )
            if(InterlockedDecrement(&m_lDel) == 0) 
        {
            delete this;
            return 0;
        }
        return m_lRef;
    }
public:
    volatile long m_lRef;
    volatile long m_lDel;
};

template<class T>
class ref_obj
{
public:
    typedef T _PtrClass;
    ref_obj()
    {
        p=0;
    }
    ref_obj(T* lp)
    {
        if ((p = lp) != 0)
            p->AddRef();
    }
    ref_obj(const ref_obj<T>& lp)
    {
        if ((p = lp.p) != 0)
            p->AddRef();
    }
    ~ref_obj()
    {
        if (p)
            p->Release();
    }
    operator  T*() const
    {
        return  p;
    }
    T& operator*() const
    {
        return *p;
    }

    /*T** operator&()
    {
        return &p;
    }*/
    T* operator->() const
    {
        return p;
    }
    T* operator=(T* lp)
    {
        if (lp != 0)
            lp->AddRef();
        if (p)
            p->Release();
        p = lp;
        return p;
    }
    T* operator=(const ref_obj<T>& lp)
    {
        if (lp != 0)
            lp->AddRef();
        if (p)
            p->Release();
        p = lp;
        return p;
    }
    bool operator!() const
    {
        return (p == 0);
    }

    T*GetObj(){return p;}

    const T*GetObj()const{return p;}
    T*p;
};

所需要被智能指针管理的类,必须要继承此基类。故此类中的引用计数存在于被管理的类中。
可以想到,这么做的好处是,将指针赋予ref_obj管理后,无需再ref_obj进行拷贝,比如对this指针的拷贝,也不用再像上面那样需要进行处理,例子如下:

  class my_class : public c_ref
  {
  public:
      my_class(int a)_a(a) {}
      virtual ~my_class() 
      {
          printf("my class destruct\n");
      }
      void print()
      {
          printf("value:%d\n", _a);
      }
  private:
      int _a;
  }

  int main(int argc, char **argv)
  {
      ref_obj<my_class> my = new my_class(123);
      my->print();
  }

但坏处也显而易见,所管理的类必须要继承c_ref类,不如shared_ptr灵活。

两者各有好处,但既然C++11中已将boost的shared_ptr纳入标准,那以后写代码,在C++11的环境下,最好还是用标准中的智能指针方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值