码迷,mamicode.com
首页 > 其他好文 > 详细

unique_ptr简谈

时间:2014-10-25 10:28:05      阅读:1948      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   io   os   ar   使用   

  看到文章里的同学留言说到unique_ptr,这两天看了一下cplusplus提供的reference才知道这个东西是c++11的新特性,对c++11的新特性不是很了解,花时间了解了下unique_ptr,之前有写过auto_ptr的分析,这里就和auto_ptr对比下来看。

  • unique_ptr的构造函数与auto_ptr一样,采用explicit声明,防止复制/拷贝时不必要的类型转换,在定义对象时必须显示调用初始化式,不能使用赋值操作符进行隐式转换。
  • unique_ptr同样要重复释放指针的可能:
    1 int _tmain(int argc, _TCHAR* argv[])
    2 {
    3      int *p = new int(12);
    4      unique_ptr<int> up(p);
    5      unique_ptr<int> up2(p);
    6  
    7      return 0;
    8 }

    up析构时,已经将p指针delete,而up2析构会重复delete,出现未定义操作。auto_ptr析构函数只是单纯的delete掉raw指针,而unique_ptr则可以定制自己的deleter,来指定unique_ptr析构时需要做哪些工作。默认情况下unique_ptr使用的deleter如下:

    1 void operator()(_Ty *_Ptr) const _NOEXCEPT
    2         {    // delete a pointer
    3         static_assert(0 < sizeof (_Ty),
    4             "can‘t delete an incomplete type");
    5         delete _Ptr;
    6         }

    可以看出这是一个函数对象,功能很简单,delete raw指针。开发人员可以定制自己的deleter,一个很简单的例子:

     1 struct my_deleter
     2 {
     3     void operator()(int *p)
     4     {
     5         cout<<"delete point, value = "<<*p<<endl;
     6         delete p;
     7     }
     8 };
     9 int _tmain(int argc, _TCHAR* argv[])
    10 {
    11     unique_ptr<int, my_deleter> up(new int(12), my_deleter());
    12 
    13     return 0;
    14 }
  • auto_ptr只能托管单独的指针,而不能用于堆上动态分配的数组。而unique_ptr则可以用于数组:
     1 struct Item
     2 {
     3      Item(){cout<<"Construct "<<endl;}
     4      ~Item() {cout<<"Destruct"<<endl;}
     5 };
     6 int _tmain(int argc, _TCHAR* argv[])
     7 {
     8      Item *par = new Item[5];
     9      unique_ptr<Item[]> uparr(par);
    10  
    11      return 0;
    12 }

     在vs2012中运行上面的代码结果如下,根据输出中五个"Destruct"可以看出uparr对象在析构时调用了delete[]:bubuko.com,布布扣

  • auto_ptr对象可以进行拷贝和赋值,之后源对象不再拥有raw指针的所有权,转而交给新对象托管。unique_ptr对象禁止拷贝和赋值运算,在vs2012源码中,将拷贝构造函数和赋值操作符声明为private,并未定义,所以如下代码中,line5,6两行均会导致编译报错:
     1 int _tmain(int argc, _TCHAR* argv[])
     2 {
     3     int *p = new int(12);
     4     unique_ptr<int> up(p);
     5     unique_ptr<int> up_copy(up);
     6     unique_ptr<int> up_assign;
     7     up_assign = up;
     8 
     9     return 0;
    10 }

    因为此特性,猜想unique_ptr对象无法很好地与STL容器一起使用(PS:最初我以为将拷贝构造和赋值操作符私有化的类,声明一个容器持有这种类型,这样的代码编译就会报错,编码后才知道编译不会报错,调用push_back等需要拷贝或赋值的操作时,才会报错),下面代码中line5将会报错:

    1 int _tmain(int argc, _TCHAR* argv[])
    2 {
    3     unique_ptr<int> up(new int(12));
    4     vector<unique_ptr<int> > vup;
    5     vup.push_back(up);
    6 
    7     return 0;
    8 }

    之后了解到c++11中引入的move语义使得unique_ptr可以存放到容器中,参考这篇文章http://www.th7.cn/Program/cp/201408/267890.shtml。使用move就表示放弃对该对象的所有权,但并不对raw指针进行释放,举个例子:

     1 int _tmain(int argc, _TCHAR* argv[])
     2 {
     3     vector<unique_ptr<int, my_deleter> > vup;
     4     {
     5         cout<<"scope begin######################"<<endl;
     6         unique_ptr<int, my_deleter> up(new int(12), my_deleter());
     7         vup.push_back(move(up));
     8         if(up.get() == NULL)
     9             cout<<"up points NULL"<<endl;
    10         cout<<"scope end######################"<<endl;
    11     }
    12     cout<<"outer######################"<<endl;
    13 
    14     return 0;
    15 }

    根据下面的输出可以验证,在局部对象up经过move函数调用后,失去了对raw指针的所有权(line9),并未释放raw指针,之后如果误用了up对象,会导致undefine行为:

    bubuko.com,布布扣

    这里需要注意的是,此处move函数调用了unique_ptr的move语意拷贝构造函数(不知道c++11是否这么称呼……),注意形参类型为unique_ptr&&

    1 unique_ptr(unique_ptr&& _Right) _NOEXCEPT
    2         : _Mybase(_Right.release(),
    3             _STD forward<_Dx>(_Right.get_deleter()))
    4         {    // construct by moving _Right
    5         }

    这里确实没有调用deleter,进行raw指针的释放。forward函数同样是c++11里的语法,表示”接受一个参数,然后返回该参数本来所对应的类型的引用”。

 

  目前对unique_ptr的了解就到这里,不算太深,可以看出unique_str的功能比auto_ptr更为强大,它支持托管堆上分配的数组,支持定制deleter,并且可以通过move语意使unique_ptr对象与容器兼容,但仍然有一些不足,比如重复释放,使用move语意之后源对象失去了对raw指针的管理权,再次使用会出现undefine行为。要避免这些情况,除了使用时要注意之外,最好的办法还是使用带有引用计数功能的智能指针。

unique_ptr简谈

标签:des   style   blog   http   color   io   os   ar   使用   

原文地址:http://www.cnblogs.com/Tour/p/4047169.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!