Freigeben über


Gewusst wie: Erstellen und verwenden Sie weak_ptr Instanzen

Manchmal Speichern eines Objekts muss eine Möglichkeit zum Zugriff auf das zugrunde liegende Objekt von einem shared_ptr ohne den Verweiszähler erhöht werden soll.Diese Situation tritt in der Regel auf, wenn stehen zyklische Verweise zwischen Ihnen shared_ptr Instanzen.

Das beste Design ist den Besitz von Zeigern zu vermeiden, wenn Sie können.Jedoch, wenn Sie den Besitz freigegeben haben, müssen shared_ptr Fällen vermeiden zyklische Verweise zwischen ihnen.Wenn zyklische Verweise aus irgendeinem Grund unvermeidlich oder sogar vorzuziehen sind, verwenden weak_ptr zu mindestens einer der Eigentümer einer schwachen Verweis auf eine andere shared_ptr.Mithilfe einer weak_ptr, können Sie eine shared_ptr , die Beitritt zu einem bestehenden Satz von verwandten Instanzen, aber nur wenn die zugrunde liegenden Speicherressource noch gültig ist.A weak_ptr sich nicht an die Verweiszählung und daher kann nicht verhindern den Verweiszähler auf 0 (null).Sie können jedoch eine weak_ptr zu versuchen, eine neue Kopie des der shared_ptr mit dem es initialisiert wurde.Wenn der Speicher bereits gelöscht wurde, ein Bad_weak_ptr Ausnahme wird ausgelöst.Wenn der Speicher noch gültig ist, wird der neue freigegebene Zeiger inkrementiert den Verweiszähler und wird sichergestellt, dass der Speicher gültig, solange die shared_ptr Variable im Gültigkeitsbereich bleiben.

Beispiel

Das folgende Codebeispiel zeigt einen Fall, in dem weak_ptr wird verwendet, um die ordnungsgemäße Löschen von Objekten zu gewährleisten, die zirkuläre Abhängigkeiten haben.Wenn Sie das Beispiel untersuchen, wird davon gegangen Sie aus, dass es erstellt wurde, nur nach alternative Lösungen betrachtet wurden.Die Controller Objekte repräsentieren einen Aspekt eines Prozesses Maschine und arbeiten unabhängig voneinander.Jeder Domänencontroller muss den Status der andere Controller jederzeit abgefragt werden, und enthält jeweils einen privaten vector<weak_ptr<Controller>> für diesen Zweck.Jeden Vektor enthält einen Zirkelverweis und daher weak_ptr Instanzen verwendet werden 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);
}

Als Experiment, ändern Sie den Vektor others werden eine vector<shared_ptr<Controller>>, und klicken Sie dann in der Ausgabe, beachten Sie, dass keine Destruktoren aufgerufen werden beim TestRun gibt.

Siehe auch

Konzepte

Intelligente Zeiger modernes (C++)