Jak: tworzenie i używanie wystąpienia weak_ptr
Czasami obiektu musi przechowywać sposób dostępu do obiektu podstawowego z shared_ptr bez powodowania licznika odwołań być zwiększane.Zazwyczaj ta sytuacja występuje, gdy masz odwołania cykliczne między shared_ptr wystąpień.
Najlepsze projektu jest uniknięcie wspólnej własności wskaźniki, w każdym przypadku, gdy można.Jednakże jeżeli zostały udostępnione własności shared_ptr wystąpień, uniknąć odwołania cykliczne między nimi.Gdy odwołania cykliczne są nieuniknione lub nawet lepiej z jakiegoś powodu, użyj weak_ptr Aby nadać jeden lub więcej właścicieli słabe odwołanie do innego shared_ptr.Za pomocą weak_ptr, można utworzyć shared_ptr dołącza do istniejącego zestawu wystąpień powiązanych, ale tylko wtedy, jeśli nadal obowiązuje podstawowych zasobów pamięci.A weak_ptr sobie nie uczestniczy w inwentaryzacji odniesienia i w związku z tym, nie zapobiega ono liczbę odwołań do zera.Można jednak użyć weak_ptr próbuje uzyskać nową kopię shared_ptr z on zainicjowany.Jeśli ilość pamięci został już usunięty, bad_weak_ptr jest wyjątek.Jeśli pamięć jest nadal ważny, wskaźnik udostępnionego zwiększa liczbę odwołań i gwarantuje, że pamięć będzie ważne tak długo, jak shared_ptr zmienna pozostaje w zakresie.
Przykład
Poniższy przykład kodu pokazuje w przypadku gdy weak_ptr jest używana do zapewnienia właściwego usuwania obiektów, które zależności cykliczne.Jako przykład można zbadać, założono, że został on utworzony tylko po rozwiązania alternatywne zostały uznane za.Controller Obiekty reprezentują niektóre aspekty procesu maszyny i działają niezależnie.Każdy kontroler musi być w stanie zbadać stan inne kontrolery w dowolnym momencie, a każdy z nich zawiera prywatny vector<weak_ptr<Controller>> w tym celu.Każdy wektor zawiera odwołanie cykliczne i dlatego, weak_ptr wystąpienia są używane zamiast 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);
}
Eksperyment, modyfikowanie wektor others za vector<shared_ptr<Controller>>, a następnie w danych wyjściowych, Zauważ, że nie destruktory są wywoływane po TestRun zwraca.
Zobacz też
Koncepcje
Inteligentne kursory (Podręcznik programowania C++ nowoczesny)