次の方法で共有


スマート ポインター (Modern C++)

最新の C++ プログラミングでは、標準のライブラリが含まれていますスマート ポインタープログラムを保証するために使用されているメモリの空きとリソース リークが発生し、例外安全が。

スマート ポインターの使用

スマート ポインターの定義では、 std名前空間で、 <memory>ヘッダー ファイル。重要なものは、 RAII またはリソース獲得は Initialialization プログラミング イディオム。この用法の主な目的は、オブジェクトのすべてのリソースが作成され、1 行のコードの準備ができるように、オブジェクトが、初期化が同時にリソースの取得が発生することができるようにです。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 バイトまたは 8 バイトのポインターと同じサイズで正確です。オーバー ロードされたスマート ポインターを使用してカプセル化されたポインターへのアクセス * し - > 演算子は、生ポインターを直接アクセスするよりもはるかに低速ではありません。

スマート ポインターは「ドット」表記を使用してアクセスされる、独自のメンバー関数があります。たとえば、いくつかの 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
      1 つの所有者が基になっているポインターのことができます。使用して、既定の選択肢として POCO の特定の必要があることがわかっていなければ、 shared_ptr。新しい所有者には、移動しますが、ないコピーまたは共有します。置換auto_ptrは推奨されません。比較boost::scoped_ptrunique_ptr小さく、効率的です。 1 つのポインターのサイズを指定し、[右辺値の参照をサポートして高速な挿入と STL コレクションから取得します。ヘッダー ファイル: <memory>。詳細については、「方法: unique_ptr インスタンスを作成して使用する」および「unique_ptr Class」を参照してください。

    • shared_ptr
      スマート ポインターの参照カウントします。コンテナーからポインターのコピーを返しますが、元を維持する場合複数所有者に、たとえば、1 つの生のポインターを割り当てるときに使用します。生ポインターまですべて削除されませんshared_ptrの所有者は、スコープ外になったまたは所有権を与えることにそれ以外の場合。サイズは、2 つのポインターです。 オブジェクトと参照カウントを含む共有コントロール ブロックのいずれかの 1 つです。ヘッダー ファイル: <memory>。詳細については、「方法: shared_ptr インスタンスを作成して使用する」および「shared_ptr クラス」を参照してください。

    • weak_ptr
      特殊なスマート ポインターの使用と組み合わせてshared_ptr。A weak_ptr 、1 つ以上を所有しているオブジェクトへのアクセスを提供するshared_ptrインスタンスしますが、参照のカウントは実行しません。オブジェクトを観察するが、それは生きて維持するを必要としない場合に使用します。場合によっては間の循環参照を解除するために必要なshared_ptrインスタンス。ヘッダー ファイル: <memory>。詳細については、「方法: weak_ptr インスタンスを作成して使用する」および「weak_ptr クラス」を参照してください。

  • COM オブジェクト (クラシック Windows プログラミング) のスマート ポインター
    COM オブジェクトを使用すると、スマート ポインターを適切な型のインターフェイス ポインターをラップします。Active Template Library (ATL) は、さまざまな用途にいくつかのスマート ポインターを定義します。使用できます、 _com_ptr_t 、.tlb ファイルからラッパー クラスを作成するときにコンパイラを使用してスマート ポインターのタイプ。ATL ヘッダー ファイルをインクルードしたくない場合は、最良の選択です。

  • ATL スマート ポインターの POCO オブジェクト
    COM オブジェクトのスマート ポインターのほかに、ATL がまたスマート ポインター、および普通の古い C++ オブジェクトは、スマート ポインターのコレクションを定義します。クラシック Windows プログラミングでは、このような便利な選択肢は、STL コレクションに特にコードの移植性が必要でない場合、または、STL と ATL のプログラミング モデルを混在させるたくないときは

    • CAutoPtr クラス
      コピーの所有権を転送することによって独自の所有権を適用するスマート ポインター。匹敵するには、非推奨std::auto_ptrクラス。

    • CHeapPtr クラス
      スマート ポインターは C を使用して割り当てられているオブジェクトのmalloc関数。

    • CAutoVectorPtr クラス
      スマート ポインターの配列を使用して割り当てられたnew[]。

    • CAutoPtrArray クラス
      クラスの配列をカプセル化するCAutoPtrの要素。

    • CAutoPtrList クラス
      リストを操作するメソッドをカプセル化するクラスCAutoPtrノード。

参照

その他の技術情報

C++ へようこそ (Modern C++)

C++ 言語リファレンス

C++ の標準ライブラリの参照

概要 : C++ のメモリ管理