C++智能指针——unique_ptr详解

前言
C++智能指针——auto_ptr详解中可以了解到auto_ptr指针的特性以及在C++11中已经被unique_ptr所代替。

unique_ptr介绍
与auto_ptr相比unique_ptr有如下特点:
1、 unique_ptr是一个独享所有权的智能指针,无法进行复制构造、赋值操作操作,只能进行移动操作。无法使两个unique_ptr指向同一个对象;
2、unique_ptr智能指向一个对象,如果当它指向其他对象时,之前所指向的对象会被摧毁。
3、unique_ptr对象会在它们自身被销毁时使用删除器自动删除它们管理的对象。
4、unique_ptr支持创建数组对象方法。

unique_ptr详解
定义:

// non-specialized	
template <class T, class D = default_delete<T>> class unique_ptr;
// array specialization	
template <class T, class D> class unique_ptr<T[],D>;

上述定义中 T 指其管理的对象类型,D 指该对象摧毁时所调用的释放方法,可以使用自定义的删除器,他也有一个默认的实现。

使用介绍
1、unique_ptr跟auto_ptr创建的方法一样。

// unique_ptr constructor example
#include <iostream>
#include <memory>

int main () {
  std::default_delete<int> d;
  std::unique_ptr<int> u1;
  std::unique_ptr<int> u2 (nullptr);
  std::unique_ptr<int> u3 (new int);
  std::unique_ptr<int> u4 (new int, d);
  std::unique_ptr<int> u5 (new int, std::default_delete<int>());
  std::unique_ptr<int> u6 (std::move(u5));
  std::unique_ptr<int> u7 (std::move(u6));
  std::unique_ptr<int> u8 (std::auto_ptr<int>(new int));

  std::cout << "u1: " << (u1?"not null":"null") << '\n';
  std::cout << "u2: " << (u2?"not null":"null") << '\n';
  std::cout << "u3: " << (u3?"not null":"null") << '\n';
  std::cout << "u4: " << (u4?"not null":"null") << '\n';
  std::cout << "u5: " << (u5?"not null":"null") << '\n';
  std::cout << "u6: " << (u6?"not null":"null") << '\n';
  std::cout << "u7: " << (u7?"not null":"null") << '\n';
  std::cout << "u8: " << (u8?"not null":"null") << '\n';

  return 0;
}

输出:

u1: null
u2: null
u3: not null
u4: not null
u5: null
u6: null
u7: not null
u8: not null

unique_ptr中不能执行copy构造函数和赋值函数原因是在代码中有如下声明:

    // Disable copy from lvalue.
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;

2、析构函数

// Destructor.
 ~unique_ptr() { reset(); }

析构函数中调用了reset函数,而reset函数的主要作用就是销毁当前由unique_ptr(如果有)管理的对象并取得p的所有权。如果p是空指针(例如默认初始化指针),则unique_ptr变为空,在调用后不管理任何对象。
ps:这里的p其实指的就是unique_ptr构造函数中class T的对象。

3、reset函数
reset函数的主要作用就是销毁当前由unique_ptr(如果有)管理的对象并取得p的所有权。具体实例:

// unique_ptr::reset example
#include <iostream>
#include <memory>

int main () {
  std::unique_ptr<int> up;  // empty

  up.reset (new int);       // takes ownership of pointer
  *up=5;
  std::cout << *up << '\n';

  up.reset (new int);       // deletes managed object, acquires new pointer
  *up=10;
  std::cout << *up << '\n';

  up.reset();               // deletes managed object

  return 0;
}

输出:

5
10

4、release函数
该函数负责释放当前管理对象的指针(即unique_ptr中class T的对象),具体使用:

// unique_ptr::release example
#include <iostream>
#include <memory>

int main () {
  std::unique_ptr<int> auto_pointer (new int);
  int * manual_pointer;

  *auto_pointer=10;

  manual_pointer = auto_pointer.release();
  // (auto_pointer is now empty)

  std::cout << "manual_pointer points to " << *manual_pointer << '\n';

  delete manual_pointer;

  return 0;
}

输出:

manual_pointer points to 10

5、get函数
返回存储的指针。

std::unique_ptr<int> foo(new int(22));
int * p = 0;
p = foo.get(); //p指向的对象为22  

6、该指针通常都是默认的删除器,不支持删除数组和不是new出来的指针,具体原因和shared_ptr一样。
扩展
unique_ptr出了上述自己实现的方法外,C++ 提供了一个 move() 库函数,可用于将对象的所有权从一个独占指针转移到另外一个独占指针。
通过move方法可以让unique_ptr被当成参数传递到方法内部,而不用担心所有权被转移而无法继续使用的问题。

std::unique_ptr<int> foo(new int(22));
std::unique_ptr<int> bar = std::move(foo);   // foo null, bar 22

参考:http://www.cplusplus.com/reference/memory/unique_ptr/
unique_ptr源码

发布了88 篇原创文章 · 获赞 17 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/yj_android_develop/article/details/88021646