次の方法で共有


方法: weak_ptr インスタンスを作成して使用する

オブジェクトの基になるオブジェクトにアクセスするための方法を保存する必要があることがあります、 shared_ptrせず、参照カウントをインクリメントしますが発生します。間の循環参照がある場合は、通常、このような状況が発生したshared_ptrインスタンス。

時のポインターの共有所有権を避けるために、最適なデザインです。ただしの所有権を共有している必要がある場合は、 shared_ptrは、それらの間の循環参照を避けます。避けられない、またはお勧めも、何らかの理由で循環参照をするときに使用weak_ptr 、所有者の 1 つ以上に、弱い参照別にshared_ptr。使用して、 weak_ptr、作成することができます、 shared_ptr 、参加だけが、関連のインスタンスの既存のセットに、基になるメモリ リソースが有効である場合。A weak_ptr自体は参照カウント参加していないし、したがって、参照カウントはゼロにならない防ぐことはできません。ただし、使用することができます、 weak_ptrの新しいコピーを入手するには、 shared_ptrが初期化されました。メモリが既に削除されている場合は、 bad_weak_ptr が例外をスローします。メモリが有効である場合は、新しい共有ポインターは参照カウントをインクリメントして、メモリが有効になることが保証されます限り、 shared_ptr変数のスコープを維持します。

使用例

場合、次のコード例を示します、 weak_ptr循環依存関係を持つオブジェクトの適切な削除を確認するために使用します。例を検討するときは、代替ソリューションのみ考慮した後、作成されたことを想定しています。Controller 、コンピューターの処理の一部を表すオブジェクトとは独立して動作します。各コント ローラーは、いつでも、他のコント ローラーの状態を照会できる必要があり、各 1 つは秘密が含まれているvector<weak_ptr<Controller>>このため。各ベクターは、循環参照が含まれているため、 weak_ptrがインスタンスを使用するのではなくshared_ptr。

#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;


class Controller 
{
public:
    int Num;
    wstring Status;
    vector<weak_ptr< Controller >> others;
    explicit Controller(int i) : Num(i) , Status(L"On")
    {
        wcout << L"Creating Controller" << Num << endl;
    }

    ~Controller()
    {
        wcout << L"Destroying Controller" << Num << endl;
    }

    // Demonstrates how to test whether the 
    // pointed-to memory still exists or not.
    void CheckStatuses() const
    {
        for_each(others.begin(), others.end(), [] (weak_ptr<Controller> wp)
        {
            try
            {
                auto p = wp.lock();
                wcout << L"Status of " << p->Num << " = " << p->Status << endl;
            }

            catch (bad_weak_ptr b)
            {
                wcout << L"Null object" << endl;
            }                
        });
    }
};

void RunTest()
{
    vector<shared_ptr< Controller >> v;
    v.push_back(shared_ptr< Controller >(new Controller(0)));
    v.push_back(shared_ptr< Controller > (new Controller(1)));
    v.push_back(shared_ptr< Controller > (new Controller(2)));
    v.push_back(shared_ptr< Controller > (new Controller(3)));
    v.push_back(shared_ptr< Controller > (new Controller(4)));

    // Each controller depends on all others not being deleted.
    // Give each controller a pointer to all the others.
    for (int i = 0 ; i < v.size(); i++)
    {
        for_each(v.begin(), v.end(), [v,i] (shared_ptr<Controller> p)
        {
            if(p->Num != i)
            {
                v[i]->others.push_back(weak_ptr<Controller>(p));
                wcout << L"push_back to v[" << i << "]: " << p->Num << endl;
            }
        });        
    }

    for_each(v.begin(), v.end(), [](shared_ptr<Controller>& p)
    {
        wcout << L"use_count = " << p.use_count() << endl;
        p->CheckStatuses();
    });
}

int main()
{    
    RunTest(); 
    wcout << L"Press any key" << endl;
    char ch;
    cin.getline(&ch, 1);
}

実験として、ベクトルを変更othersにはvector<shared_ptr<Controller>>とし、出力では、デストラクターが呼び出されるしないことに注意するくださいとTestRunを返します。

参照

概念

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