1. 程式人生 > 實用技巧 >C++11智慧指標

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);

輸出: