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

      对于动态申请的内存,C++语言为我们提供了new和delete运算符, 而没有像java一样,提供一个完整的GC机制,因此对于我们申请的动态内存,我们需要时刻记得释放,且不能重复释放,释放后不能再去使用...  因此在使用时造成很多不便,且容易出现很多问题,一旦出问题就造成core dump,程序直接挂掉 , 这个时候,智能指针的优势就体现出来了,智能指针符合RAII原则,资源获取就是初始化,在对象析构时,将资源进行释放,对动态内存做到一个比较好的管理

      unique_ptr 持有对对象的独有权—两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作

      unique_ptr拥有所有auto_ptr的功能,且unique_ptr通过将复制构造和赋值操作符私有化,将对象的所有权独有,很好的将auto_ptr的安全问题给规避掉了,unique_ptr的其他特点包括:1.提供删除器释放对象,允许用户自定义删除器 2.添加了对象数组的偏特化实现,new[],delete[] 3.使用C++ 11的右值引用特性,实现所有权转移 std::move()

      本次实现,将unique_ptr的基本接口进行了实现,基本包括了unique_ptr的功能  (编译平台:Linux centos 7.0 编译器:gcc 4.8.5 )

      使用std::unique_ptr时,需要#include <memory>头文件,具体使用代码如下(文件名:test_ptr.cpp):

     1 #include <memory>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 class Test
     7 {
     8 public:
     9     Test()
    10     {
    11         cout << "construct.." << endl;
    12     }
    13     
    14     ~Test()    
    15     {
    16         cout << "destruct.." << endl;
    17     }
    18 };
    19 
    20 void test()
    21 {
    22     
    23 }
    24 
    25 int main()
    26 {
    27     //auto_ptr
    28     Test* p = new Test(); 
    29     auto_ptr<Test> ap(p);
    30     
    31     //unique_ptr
    32     Test* p1 = new Test();
    33     unique_ptr<Test> up(new Test());
    34     unique_ptr<Test> up1(move(up));
    35 
    36     
    37 
    38     //unique_ptr<Test> up2 = up;
    39     
    40     unique_ptr<int> up3(new int(5));
    41 
    42     return 0;
    43 }

      具体实现代码如下,没有对动态对象数组及std::move()进行实现,动态对象数组实现代码和这差不多,写个模板偏特化即可,至于std::move()则和成员函数release()类似,转移所有权(文件名:unique_ptr_implement.cpp):

      1 #include <iostream>
      2 #include <assert.h>
      3 
      4 using namespace std;
      5 
      6 #define PTR_ASSERT(x) assert(x)
      7 
      8 template<class T>
      9 struct defalute_deleter
     10 {
     11     void defalute_deleter_method()
     12     {
     13         cout << "deleter method..." << endl;
     14     }
     15     void operator()(T* ptr)
     16     {
     17         if(ptr != NULL)
     18         {
     19             cout << "default deleter....." << endl;
     20             delete ptr;
     21             ptr = NULL;
     22         }
     23     }
     24 };
     25 
     26 template<typename T, typename deleter = defalute_deleter<T> >
     27 class unique_ptr
     28 {
     29 public:
     30     explicit unique_ptr(T* ptr = NULL);
     31     
     32     unique_ptr(T* ptr, deleter d);
     33 
     34     ~unique_ptr();
     35 
     36     T* get();
     37 
     38     void reset(T* ptr = NULL);
     39 
     40     deleter& getDeleter();
     41 
     42     T* release();
     43 
     44 public:
     45     T& operator*();    
     46     
     47     T* operator->();
     48 
     49     operator bool() const;
     50     
     51 private:
     52     unique_ptr(unique_ptr& up);
     53 
     54     unique_ptr& operator = (unique_ptr& up);
     55     
     56 private:
     57     T* m_ptr;
     58 
     59     deleter m_deleter;
     60 };
     61 
     62 template<typename T, typename deleter>
     63 unique_ptr<T, deleter>::unique_ptr(T* ptr /* = NULL */, deleter d)
     64 {
     65     if(ptr != NULL)
     66     {
     67         m_ptr = ptr;
     68         m_deleter = d;
     69     }
     70 }
     71 
     72 template<typename T, typename deleter>
     73 unique_ptr<T, deleter>::unique_ptr(T* ptr /* = NULL */)
     74 {
     75     if(ptr != NULL)
     76     {
     77         m_ptr = ptr;
     78     }    
     79 }
     80 
     81 template<typename T, typename deleter>
     82 unique_ptr<T, deleter>::~unique_ptr()
     83 {
     84     if(m_ptr != NULL)
     85     {
     86         m_deleter(m_ptr);
     87         m_ptr = NULL;
     88     }
     89 }
     90 
     91 template<typename T, typename deleter>
     92 T& unique_ptr<T, deleter>::operator*()
     93 {
     94     PTR_ASSERT(m_ptr != NULL);
     95 
     96     return *m_ptr;
     97 }
     98 
     99 template<class T, class deleter>
    100 T* unique_ptr<T, deleter>::operator->()
    101 {
    102     PTR_ASSERT(m_ptr != NULL);
    103 
    104     return m_ptr;
    105 }
    106 
    107 template<typename T, typename deleter>
    108 T* unique_ptr<T, deleter>::get()
    109 {
    110     return m_ptr;
    111 }
    112 
    113 template<typename T, typename deleter>
    114 void unique_ptr<T, deleter>::reset(T* ptr)
    115 {
    116     T* old_ptr = m_ptr;
    117     m_ptr = ptr;
    118 
    119     if(old_ptr != NULL)
    120     {
    121         m_deleter(old_ptr);
    122         old_ptr = NULL;
    123     }
    124 }
    125 
    126 template<typename T, typename deleter>
    127 deleter& unique_ptr<T, deleter>::getDeleter()
    128 {
    129     return m_deleter;
    130 }
    131 
    132 template<typename T, typename deleter>
    133 T* unique_ptr<T, deleter>::release()
    134 {
    135     T* pTemp = m_ptr;
    136     m_ptr = NULL;
    137 
    138     return pTemp;    
    139 }
    140 
    141 template<typename T, typename deleter>
    142 unique_ptr<T, deleter>::operator bool() const
    143 {
    144     return m_ptr != NULL;
    145 }
    146 
    147 
    148 //Test class
    149 class Test
    150 {
    151 public:
    152     Test()
    153     {
    154         cout << "construct.." << endl;
    155     }
    156     
    157     ~Test()    
    158     {
    159         cout << "destruct.." << endl;
    160     }
    161 
    162     void method()
    163     {
    164         cout << "welcome Test.." << endl;
    165     }
    166 };
    167 
    168 //custom deleter
    169 template <class T>
    170 struct custom_deleter
    171 {
    172     void deleter_method()
    173     {
    174         cout << "custom deleter method..." << endl;
    175     }
    176 
    177     void operator()(T* ptr)
    178     {
    179         cout << "custom deleter... " << endl;
    180         delete ptr;
    181         ptr = NULL;
    182     }
    183 };
    184 
    185 
    186 int main()
    187 {
    188     //default deleter
    189     cout << "=======default deleter====interface test begin: ========== " << endl;
    190     unique_ptr<Test> up(new Test());
    191     
    192     cout << "operator ->: " << endl;
    193     up->method();
    194     
    195     cout << "operator *: " << endl;
    196     (*up).method();
    197 
    198     cout << "operator bool: " << endl;
    199     if(up){ cout<< "obj is exit" << endl;}
    200 
    201     cout << "get: " << endl;
    202     up.get()->method();
    203 
    204     cout << "getDeleter: " << endl;
    205     defalute_deleter<Test> del = up.getDeleter();
    206     del.defalute_deleter_method();
    207 
    208     cout << "release: " << endl;
    209     unique_ptr<Test> up1(up.release());
    210 
    211     //if take this,  will die
    212     //(*up).method();
    213 
    214     cout << "reset: " << endl;
    215     up1.reset();
    216 
    217     //Custom deleter
    218     cout << "=======Custom deleter====interface test begin: ========== " << endl;
    219     custom_deleter<Test> d;
    220     unique_ptr<Test, custom_deleter<Test> > up_custom_dele(new Test(), d);
    221     
    222     cout << "operator ->: " << endl;
    223     up_custom_dele->method();
    224     
    225     cout << "operator *: " << endl;
    226     (*up_custom_dele).method();
    227 
    228     cout << "operator bool: " << endl;
    229     if(up_custom_dele){ cout<< "obj is exit" << endl;}
    230 
    231     cout << "get: " << endl;
    232     up_custom_dele.get()->method();
    233 
    234     cout << "getDeleter: " << endl;
    235     custom_deleter<Test> custom_del = up_custom_dele.getDeleter();
    236     custom_del.deleter_method();
    237 
    238     cout << "release: " << endl;
    239     unique_ptr<Test> up3(up_custom_dele.release());
    240 
    241     //if take this,  will die
    242     //(*up_custom_dele).method();
    243 
    244     cout << "reset: " << endl;
    245     up3.reset();
    246     
    247 
    248     return 0;
    249 }

      执行代码,打印如下:

     1 [root@localhost code]# g++ -o unique unique_ptr_implement.cpp 
     2 [root@localhost code]# ./unique
     3 =======default deleter====interface test begin: ========== 
     4 construct..
     5 operator ->: 
     6 welcome Test..
     7 operator *: 
     8 welcome Test..
     9 operator bool: 
    10 obj is exit
    11 get: 
    12 welcome Test..
    13 getDeleter: 
    14 deleter method...
    15 release: 
    16 reset: 
    17 default deleter.....
    18 destruct..
    19 =======Custom deleter====interface test begin: ========== 
    20 construct..
    21 operator ->: 
    22 welcome Test..
    23 operator *: 
    24 welcome Test..
    25 operator bool: 
    26 obj is exit
    27 get: 
    28 welcome Test..
    29 getDeleter: 
    30 custom deleter method...
    31 release: 
    32 reset: 
    33 default deleter.....
    34 destruct..
    35 [root@localhost code]# 

      从实现结果可以看出,unique_ptr保证一个动态对象只有一个unique_ptr对象所拥有,unique_ptr对象之间无法copy和赋值,只能进行动态内存对象的转移,转移时,原有的unique_ptr对象将不再拥有动态内存的访问权限,这样可以保证动态内存使用的安全性。在实现中构造函数提供了两个,一个使用默认删除器,另一个则需要我们构造时传入删除器,这样可以很好的进行资源自定义删除。 对于多个指针对象指向同一个动态内存对象,unique_ptr不适用,需使用share_ptr

  • 相关阅读:
    【spring 事务注解配置】事务回滚
    myisam 和 innodb 对比
    mysql replace into用法详细说明
    [nginx] 配置
    【lucene】中文分词
    Lucene 4.9 document的简单应用
    Spring事务配置的五种方式
    Open-Drain与Push-Pull
    HDMI中的AVmute是什么功能
    在Keil uv5里面添加STC元器件库,不影响其他元件
  • 原文地址:https://www.cnblogs.com/blog-yejy/p/8972858.html
Copyright © 2011-2022 走看看