什麼是智能指針,什麼時候應使用?

什麼是智能指針,什麼時候應使用? html


#1樓

http://en.wikipedia.org/wiki/Smart_pointer 程序員

在計算機科學中,智能指針是一種抽象數據類型,它在提供其餘功能(例如自動垃圾收集或邊界檢查)的同時模擬指針。 這些附加功能旨在減小因濫用指針而致使的錯誤,同時保持效率。 智能指針一般會跟蹤指向它們的對象,以進行內存管理。 指針的濫用是錯誤的主要來源:必須由使用指針編寫的程序執行常量分配,釋放和引用,這極可能會發生一些內存泄漏。 智能指針試圖經過使資源自動分配來防止內存泄漏:當指向某個對象的指針(或一系列指針中的最後一個)被破壞時,例如,因爲超出範圍,指向的對象也將被破壞。 安全


#2樓

智能指針就像常規的(類型化的)指針同樣,如「 char *」,除了當指針自己超出範圍時,它所指向的內容也會被刪除。 您能夠像使用常規指針同樣使用「->」來使用它,可是若是您須要一個實際的數據指針,則不須要。 爲此,您可使用「&* ptr」。 併發

它對: app

  • 必須分配給new的對象,但您但願擁有與該堆棧上的對象相同的生存期。 若是將對象分配給智能指針,則在程序退出該功能/塊時將刪除它們。 函數

  • 類的數據成員,以便在刪除對象時也刪除全部擁有的數據,而在析構函數中沒有任何特殊代碼(您須要確保析構函數是虛擬的,這幾乎老是一件好事) 。 ui

你可能但願使用智能指針時: spa

  • ...指針實際上不該該擁有數據...,即,當您僅使用數據時,可是您但願它在引用它的函數中存活下來。
  • ...智能指針自己不會在某個時候被破壞。 您不但願它位於永不被破壞的內存中(例如,在動態分配但不會被明確刪除的對象中)。
  • ...兩個智能指針可能指向同一數據。 (可是,還有更聰明的指針能夠處理此問題……這稱爲引用計數 。)

也能夠看看: 指針


#3樓

大多數類型的智能指針都會爲您處理指向對象的處理。 這很是方便,由於您沒必要再​​考慮手動處理對象。 code

最經常使用的智能指針是std::tr1::shared_ptr (或boost::shared_ptr ),以及std::auto_ptr 。 我建議按期使用shared_ptr

shared_ptr很是通用,能夠處理各類處置方案,包括須要「跨越DLL邊界傳遞對象」的狀況(若是在代碼和DLL之間使用不一樣的libc則一般是噩夢)。


#4樓

智能指針是一種相似指針的類型,具備一些其餘功能,例如自動內存釋放,引用計數等。

智能指針-什麼,爲何,哪一個頁面上提供了小型介紹

一種簡單的智能指針類型是std::auto_ptr (C ++標準的20.4.5章),它容許在超出範圍時自動釋放內存,而且比引起異常時的簡單指針使用更可靠,儘管這種狀況較少靈活。

另外一個方便的類型是boost::shared_ptr ,它實現引用計數並在沒有剩餘對對象的引用時自動釋放內存。 這有助於避免內存泄漏,而且易於使用來實現RAII

David Vandevoorde的《 C ++模板:完整指南》一書在Nicolai M. Josuttis的第20章「智能指針」中進行了詳細介紹。 涵蓋了一些主題:


#5樓

更新

這個答案很舊,所以描述了當時的「好」,這是Boost庫提供的智能指針。 從C ++ 11開始,標準庫提供了足夠的智能指針類型,所以您應該同意使用std::unique_ptrstd::shared_ptrstd::weak_ptr

還有std::auto_ptr 。 它很是相似於做用域指針,不一樣之處在於它還具備「特殊」危險功能,可被複制-還會意外地轉移全部權。
它在C ++ 11中已棄用,在C ++ 17中已刪除 ,所以您不該該使用它。

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

老答案

智能指針是包裝「原始」(或「裸露」)C ++指針的類,用於管理所指向對象的生命週期。 沒有單一的智能指針類型,可是它們都嘗試以一種實用的方式抽象一個原始指針。

智能指針應優於原始指針。 若是您以爲須要使用指針(首先考慮是否確實須要使用指針),則一般但願使用智能指針,由於這能夠減輕原始指針的許多問題,主要是忘記刪除對象和泄漏內存。

使用原始指針,程序員必須在再也不有用時顯式銷燬該對象。

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?

經過比較,智能指針定義了有關銷燬對象的時間的策略。 您仍然必須建立對象,可是沒必要擔憂銷燬它。

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

使用的最簡單策略涉及智能指針包裝器對象的範圍,例如經過boost::scoped_ptrstd::unique_ptr

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

請注意,沒法複製std::unique_ptr實例。 這樣能夠防止屢次(不正確)刪除指針。 可是,您能夠將對其的引用傳遞給您調用的其餘函數。

若是要將對象的生存期綁定到特定代碼塊,或者將其做爲成員數據嵌入另外一個對象的生存std::unique_ptrstd::unique_ptr頗有用。 該對象將一直存在,直到退出包含代碼的塊,或者直到包含對象自己被銷燬爲止。

更復雜的智能指針策略涉及對指針進行引用計數。 這確實容許複製指針。 當該對象的最後一個「引用」被銷燬時,該對象將被刪除。 該策略由boost::shared_ptrstd::shared_ptr

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

當對象的生存期很是複雜,而且不直接與代碼的特定部分或另外一個對象綁定時,引用計數的指針很是有用。

引用計數的指針有一個缺點-可能建立懸掛的引用:

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

另外一種可能性是建立循環引用:

struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

要變通解決此問題,Boost和C ++ 11都定義了weak_ptr來定義對shared_ptr的弱(未計數)引用。

相關文章
相關標籤/搜索