天天看點

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源碼

繼續閱讀