前言
從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源碼