Visual C++ 2010 でshared_ptr

この度、Visual Studio 2010からC++0xのshared_ptrを使うことができるようになったということで試してみました。

  • まず、2つのshared_ptrで整数型の配列を参照する例(ソースコードについて、コメントを頂きましたため、修正いたしました。)
  • #include <stdio.h>
    #include <memory>
    
    int main()
    {
        const int SIZE = 5;
    
        std::tr1::shared_ptr<int> p1(new int[SIZE], 
            [](int* ptr) { delete [] ptr; });//配列型は、delete [] ptr; とメモリを解放する必要がある
    
        //std::tr1::shared_ptr<int> p1(new int[SIZE]);//int型の配列を確保
        std::tr1::shared_ptr<int> p2;
        
        //p1が参照しているint型配列の値を設定する
        for (int i = 0; i < SIZE; i++) {
            p1.get()[i] = i;
        }
    
        //p1、p2が同じint型配列を参照する
        p2 = p1;
    
        //参照カウントを表示
        printf("use_count: %d\n\n", p1.use_count());
    
        //p1、p2が参照している配列の要素を変更する
        p1.get()[0] = 999;
        p2.get()[1] = 999;
    
    
        //p1, p2それぞれの配列の要素を表示する
        for (int i = 0; i < SIZE; i++) {
            printf("p1[%d] = %d\n", i, p1.get()[i]);
        }
        puts("\n");
        for (int i = 0; i < SIZE; i++) {
            printf("p2[%d] = %d\n", i, p2.get()[i]);
        }
    
        return 0;
    }


  • 実行結果

  • p2 = p1 が実行された後で、参照カウンタが「2」になっている。p1、p2それぞれの参照先の要素の変更も反映されていることがわかる。

    use_count: 2
    
    <span class="deco" style="color:#FF0000;">p1[0] = 999
    p1[1] = 999</span>
    p1[2] = 2
    p1[3] = 3
    p1[4] = 4
    
    
    <span class="deco" style="color:#FF0000;">p2[0] = 999
    p2[1] = 999</span>
    p2[2] = 2
    p2[3] = 3
    p2[4] = 4
    





    次に、オブジェクトが破棄される(デストラクタが呼ばれる)タイミングを以下のコードで調べてみる。

  • オブジェクトが破棄されるタイミングを調べるためのコード
  • #include <stdio.h>
    #include <memory>
    
    class MyClass {
    public:
        ~MyClass() {
            printf("Destructor called\n");
        }
    };
    
    int main()
    {
        std::tr1::shared_ptr<MyClass> p1;
        std::tr1::shared_ptr<MyClass> p2;
    
        printf("p1.use_count: %d\n", p1.use_count());
    
        p1.reset(new MyClass());
    
        printf("p1.use_count: %d\n", p1.use_count());
    
        //p1とp2が同じMyClassオブジェクトを参照する
        p2 = p1;
    
        printf("p1.use_count: %d\n", p1.use_count());
    
        p1 = NULL;
    
        printf("p1.use_count: %d\n", p1.use_count());
        
        p2 = NULL;//ここで参照カウントがゼロになり、デストラクタが呼ばれる
    
        return 0;
    }


  • 実行結果

  • 1つのMyClassオブジェクトを参照するshared_ptrが増える度に、参照カウンタが増加することが分かる。
    そして、shared_ptrにNULLを代入すると参照カウンタが減少し、参照カウンタがゼロになるとMyClassオブジェクトのデストラクタが呼ばれる。

    p1.use_count: 0
    p1.use_count: 1
    p1.use_count: 2
    p1.use_count: 1
    Destructor called
    



    参考
    http://msdn.microsoft.com/ja-jp/library/bb982026.aspx
    http://blog.livedoor.jp/hkoie/archives/51164311.html