智慧型指標 (現代的 C++)

在現今的 C++ 程式設計中,這個標準的程式庫共有智慧型指標,這用來協助您確保程式的程式不再受制於記憶體和資源遺漏的詳細資訊,是安全的例外狀況。

智慧型指標的用法

智慧型指標定義在std命名空間中的<memory>標頭檔。 它們是很重要 RAII 或資源擷取是 Initialialization 的程式設計習慣用法。 這個慣用語的主要目標是確保資源擷取進行一次初始化物件,使所有資源的物件將被建立並可在一行程式碼中。 實際上,RAII 的主要原則是讓任何堆積配置資源的擁有權 — 例如,動態配置的記憶體或系統物件控點 — 為堆疊配置的物件,其解構函式包含的程式碼,將其刪除,或釋出資源,以及任何相關聯的清除程式碼。

在大部分的情況下時您初始化為指向實際資源的原始指標] 或 [資源控制代碼,給予指標的智慧型指標立即。 在現代化 C++ 中,只會用於小的程式碼區塊的有限範圍、 迴圈或協助程式函式是很重要的效能,並沒有機會的擁有權的混淆的未經處理的指標。

下列範例會比較的智慧型指標宣告的未經處理的指標宣告。

void UseRawPointer()
{
    // Using a raw pointer -- not recommended.
    Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); 

    // Use pSong...

    // Don't forget to delete!
    delete pSong;   
}


void UseSmartPointer()
{
    // Declare a smart pointer on stack and pass it the raw pointer.
    unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));

    // Use song2...
    wstring s = song2->duration_;
    //...

} // song2 is deleted automatically here.

如範例所示,智慧型指標就會是類別樣板,在堆疊上,宣告及初始化使用未經處理的指標指向堆積配置的物件。 智慧型指標已經初始化之後,它會負責將未經處理的指標。。 這表示智慧型指標是負責刪除未經處理的指標指定的記憶體。 智慧型指標解構函式包含要刪除,請呼叫而智慧型指標在堆疊上宣告的因為其解構函式時所叫用智慧型指標超出範圍,即使發生例外狀況中某處進一步的堆疊上。

使用熟悉的指標的運算子,來存取封裝的指標->和*,其中的智慧型指標類別多載來傳回封裝未經處理的指標。

C + + 智慧型指標慣用句類似物件的建立,這些語言中 C#: 您建立物件,然後讓系統負責處理的刪除它在適當時間。 不同之處在於任何個別的記憶體回收行程執行在背景中。 透過標準的 C++ 範圍設定規則,使執行階段環境更快且更有效管理記憶體。

重要

永遠建立智慧型指標分開於各行程式碼,永遠不會在參數清單,如此細微的資源流失就不會受限於特定的參數清單配置規則。

下列範例所示如何unique_ptr從標準樣板程式庫的智慧型指標型別可以用來封裝大型物件的指標。


class LargeObject
{
public:
    void DoSomething(){}
};

void ProcessLargeObject(const LargeObject& lo){}
void SmartPointerDemo()
{    
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass a reference to a method.
    ProcessLargeObject(*pLarge);

} //pLarge is deleted automatically when function block goes out of scope.

範例將示範下列使用智慧型指標的基本步驟。

  1. 將智慧型指標宣告為執行自動 (本機) 的變數中。 (請不要使用new或malloc在本身的智慧型指標運算式。)

  2. 在型別參數,指定被指到封裝指標型別。

  3. 傳遞的未經處理的指標, new-ed 智慧型指標建構函式中的物件。 (有些公用程式函式或智慧型指標建構函式為您做到這。)

  4. 使用多載->和*用來存取物件的運算子。

  5. 可讓智慧型刪除該物件的指標。

智慧型指標被為了盡量有效率這兩個記憶體和效能。 比方說,唯一的資料成員在unique_ptr是封裝的指標。 這表示unique_ptr是完全相同的大小為 4 個位元組或八個位元組的指標。 使用多載的智慧型指標來存取封裝的指標 1 和-> 運算子不明顯慢於直接存取的未經處理的指標。

智慧型指標有它們自己的成員函式,可藉由使用 「 點 」 標記法所存取。 比方說,有些 STL 智慧型指標有釋放指標的擁有權的重設成員函式。 當您想要釋放記憶體所擁有的智慧型指標之前的智慧型指標超出範圍,如下列範例所示,這非常有用。

void SmartPointerDemo2()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Free the memory before we exit function block.
    pLarge.reset();

    // Do some other work...

}

智慧型指標通常會提供一個可以直接存取其未經處理的指標。 STL 智慧型指標有get成員函式,為上述目的,以及CComPtr有公用p類別成員。 藉由提供直接存取基礎的指標,您可以使用自己的程式碼中管理記憶體,並仍將未經處理的指標傳遞給不支援智慧型指標的程式碼的智慧型指標。

void SmartPointerDemo4()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass raw pointer to a legacy API
    LegacyLargeObjectFunction(pLarge.get());    
}

類型的智慧型指標

下一節摘要說明可用於 Windows 程式設計環境的智慧型指標不同的種類,並說明使用時機。

  • C + + 標準程式庫的智慧型指標
    使用這些智慧型指標這樣的第一個選項,來封裝一般的舊 C++ 物件 (POCO) 的指標。

    • unique_ptr
      可讓基礎的指標正好與其中一個擁有者。 使用以預設選項為 POCO,除非您確知您需要shared_ptr。 可移至新的擁有者,但不是複製或共用。 取代auto_ptr,它已被取代。 若要比較boost::scoped_ptrunique_ptr小型且有效率。 這個大小是一個指標,且快速插入和擷取來自 STL 集合支援右值的參考。 標頭檔: <memory>。 如需詳細資訊,請參閱 How to: 建立和使用 unique_ptr 執行個體unique_ptr Class

    • shared_ptr
      參考計數的智慧型指標。 當您想要指派給擁有多個者,比方說,一個未經處理的指標,當您從容器傳回指標的複本,但想要保留原始時使用。 未經處理的指標不會刪除一直到所有shared_ptr的擁有者已經超出範圍,或否則已經背棄擁有權。 這個大小是兩個指標 ; 其中一個物件和另一個則用於包含參考計數的共用的控制區塊。 標頭檔: <memory>。 如需詳細資訊,請參閱 How to: 建立和使用 shared_ptr 執行個體shared_ptr Class

    • weak_ptr
      特殊的智慧型指標是否為用來與shared_ptr。 A weak_ptr提供物件是由一或多所擁有的存取權shared_ptr執行個體,但並未用來建立參考計數。 當您想要看到物件,但不是需要它保持存留時使用。 在某些情況下,才能中斷之間的循環參考shared_ptr執行個體。 標頭檔: <memory>。 如需詳細資訊,請參閱 How to: 建立和使用 weak_ptr 執行個體weak_ptr Class

  • 智慧型指標的 COM 物件 (傳統 Windows 程式設計)
    當您使用 COM 物件時,請以適當的智慧型指標型別的包裝介面指標。 使用中的樣板程式庫 (ATL) 會定義幾個智慧型指標適合各種用途。 您也可以使用**_com_ptr_t**的智慧型指標型別,編譯器會使用建立包裝函式類別來自.tlb 檔案時。 當您不想包含的 ATL 標頭檔時,它就會是最佳的選擇。

  • 對於 POCO 物件的 ATL 智慧型指標
    除了 COM 物件的智慧型指標,ATL 也會定義智慧型指標,以及一般舊的 C++ 物件的智慧型指標的集合。 在傳統 Windows 程式設計中,這些型別是很有用的替代項目 STL 集合中,尤其不是是必要的程式碼可攜性,或當您不想以調配適當的程式撰寫模型,STL 和 ATL.

請參閱

其他資源

歡迎回到 C++ (現代的 C++)

C + + 語言參考

標準 C++ 程式庫參考

在 C++ 程式概觀: 記憶體管理