C++11智慧指標
Smart Pointers - What, Why, Which?http://ootips.org/yonat/4dev/smart-pointers.html
auto_ptr
C++98中,智慧指標通過一個模板型別auto_ptr實現,缺點:拷貝時返回一個左值,不能呼叫delete[](只能針對單個物件使用,不能針對陣列使用),所以在C++11標誌中被廢棄了。
auto_ptr的一種實現方式,可以看到在解構函式中呼叫的是:delete ptr;
C++11標誌引入了:unique_ptr、shared_ptr、weak_ptr來自動回收堆分配的物件。
unique_ptr
與所指定物件的記憶體繫結緊密,不能與其他unique_ptr型別的指標物件共享所指物件的記憶體,每個unique_ptr都是唯一地擁有指向物件的記憶體。可通過std::move函式來轉移所指物件記憶體的所有權,在通過move函式轉移後,原來的unique_ptr不在擁有記憶體,再通過該指標指向記憶體會導致執行時錯誤。
可通過呼叫reset()函式來顯示釋放記憶體。
成員函式:
- get
return the stored pointer,返回儲存的指標,The stored pointer to the object managed by the unique_ptr, if any, or to nullptr if the unique_ptr is empty.呼叫該函式並不會使得unique_ptr失去所指向物件的所有權。
- get_deleter
return the stored deleter,獲取儲存的刪除器,The stored deleter is a callable object.deleter用於當unique_ptr在析構、被分配一個新值,或reset函式呼叫時自動呼叫,用於刪除所指向的物件。
- operator=
check if not empty,判斷一個unique_ptr當前是否擁有一個物件,如果unique_ptr是empty,返回false;其他情況返回true
// example of unique_ptr::operator bool #include <iostream> #include <memory> int main () { std::unique_ptr<int> foo; std::unique_ptr<int> bar (new int(12)); if (foo) std::cout << "foo points to " << *foo << '\n'; else std::cout << "foo is empty\n"; if (bar) std::cout << "bar points to " << *bar << '\n'; else std::cout << "bar is empty\n"; return 0; }
- release:
Releases ownership of its stored pointer, by returning its value and replacing it with anull pointer.This call does not destroy the managed object, but theunique_ptrobject is released from the responsibility of deleting the object.Some other entity must take responsibility for deleting the object at some point.
也就是說:呼叫release函式只是讓unique_ptr放棄對所指向物件的所有權,但是並不會析構所指向物件,需要其他的方式來釋放所指向物件的記憶體。
- reset
void reset (pointer p = pointer()) noexcept;
析構當前unique_ptr所指向的物件,並獲取p指標的所有權。如果p是一個null pointer,unique_ptr會成為empty,在函式呼叫後不再擁有任何物件。如果想要釋放unique_ptr對物件的所有權但是不析構所指向的物件,使用release函式。
- swap
void swap (unique_ptr& x) noexcept;
Exchanges the contents of theunique_ptrobject with those ofx, transferring ownership of any managed object between them without destroying either.
The function swaps the respectivestored pointersandstored deletersby invokingswapon them.
// unique_ptr::swap example #include <iostream> #include <memory> int main () { std::unique_ptr<int> foo (new int(10)); std::unique_ptr<int> bar (new int(20)); foo.swap(bar); std::cout << "foo: " << *foo << '\n'; std::cout << "bar: " << *bar << '\n'; return 0; }
- operator*
return a reference to the managed object.返回一個指向所管理物件的引用。
- operator->
return a pointer to the managed object in order to access one of its members.獲取一個指向所管理物件的指標,用於訪問其成員。
shared_ptr
Manages the storage of a pointer, providing a limitedgarbage-collectionfacility, possibly sharing that management with other objects.
與其他的shared_ptr共同擁有指向某物件的所有權,當最後一個指向該物件的shared_ptr結束生命週期時才會呼叫解構函式釋放所指向物件的記憶體。只有通過拷貝shared_ptr才會共享所有權。如果兩個shared_ptr通過建構函式建立的,即使構造它們的是同一個物件,它們也不會共享所有權,這就會導致風險,因為可能一個shared_ptr已經釋放了記憶體,而另外一個此時再訪問就會導致錯誤。
另外,shared_ptr物件可以在共享一個指標的所有權的同時,指向另一個物件。該功能成為aliasing(見建構函式:http://www.cplusplus.com/reference/memory/shared_ptr/shared_ptr/),通常用於在擁有物件的所有權的同時指向物件的成員。由於該功能的存在,一個shared_ptr可能與兩個指標相關聯:
- Astored pointer, which is the pointer it is said topoint to, and the one itdereferenceswithoperator*. shared_ptr在呼叫operator*獲取到的。
- Anowned pointer(possibly shared), which is the pointer the ownership group is in charge of deleting at some point, and for which itcounts as a use. 與其他shared_ptr共享的指標,並負責該物件的析構。
通常情況下,shared_ptr的stored pointer和owned pointer指向同一個物件,但是alias shared_ptr物件(those constructed with the aliasconstructorand their copies)可能指向不同的物件。
一個不擁有任何指標所有權的shared_ptr是一個空(empty)shared_ptr。一個不指向任何物件的shared_ptr是一個null shared_ptr。注意兩者不相等。
成員函式:
- use_count
返回共享shared_ptr物件指向同一物件的數量
- unique
Returns whether theshared_ptrobject does not share ownership over its pointer with othershared_ptrobjects (i.e., it isunique).
weak_ptr
weak_ptr可以指向記憶體的一個shared_ptr物件,卻不擁有該記憶體。使用weak_ptr的成員函式lock,可以返回其指向記憶體的一個shared_ptr,且在所指向物件記憶體已經無效時,返回nullptr。這可以驗證shared_ptr智慧指標的有效性。
#include <memory> void check(weak_ptr<int>& wp) { shared_ptr<int> sp = wp.lock();//轉換為shared_ptr if (sp != nullptr) { cout << "still " << *sp << endl; } else { cout << "pointer is invalid" << endl; } } int main(int argc, char *argv[]) { //weak-ptr===== shared_ptr<int> sp1(new int(22)); shared_ptr<int> sp2 = sp1; //使用拷貝構造,共享所有權 weak_ptr<int> wp = sp1; //指向shared_ptr<int>所指物件 cout << *sp1 << endl; cout << *sp2 << endl; check(wp); sp1.reset(); cout << *sp2 << endl; check(wp); sp2.reset(); check(wp);
輸出: