Instrukcje: tworzenie i używanie wystąpień weak_ptr
Czasami obiekt musi przechowywać sposób uzyskiwania dostępu do bazowego obiektu shared_ptr bez powodowania przyrostowania liczby odwołań. Zazwyczaj taka sytuacja występuje, gdy istnieją cykliczne odwołania między shared_ptr
wystąpieniami.
Najlepszym rozwiązaniem jest unikanie współużytkowania własności wskaźników za każdym razem, gdy jest to możliwe. Jeśli jednak musisz mieć współwłaścicieli wystąpienia shared_ptr
, unikaj cyklicznych odwołań między nimi. Jeśli odwołania cykliczne są nieuniknione, a nawet preferowane z jakiegoś powodu, użyj weak_ptr , aby dać jednemu lub kilku właścicielom słabe odwołanie do innego shared_ptr
. Za pomocą klasy weak_ptr
można utworzyć obiekt shared_ptr
, który łączy się z istniejącym zestawem powiązanych wystąpień, ale tylko wtedy, gdy bazowy zasób pamięci jest nadal prawidłowy. Sam element weak_ptr
nie uczestniczy w zliczaniu odwołań i dlatego nie może uniemożliwić, aby liczba odwołań przechodziła do zera. Można jednak użyć obiektu , weak_ptr
aby spróbować uzyskać nową kopię obiektu shared_ptr
, za pomocą którego został zainicjowany. Jeśli pamięć została już usunięta, operator wartości logicznej weak_ptr
"s" zwraca wartość false
. Jeśli pamięć jest nadal prawidłowa, nowy wskaźnik współużytkowany zwiększa liczbę odwołań i gwarantuje, że pamięć będzie prawidłowa, o ile shared_ptr
zmienna pozostanie w zakresie.
Przykład
Poniższy przykład kodu przedstawia przypadek, w którym weak_ptr
jest używany w celu zapewnienia prawidłowego usunięcia obiektów, które mają zależności cykliczne. Podczas badania przykładu załóżmy, że został on utworzony dopiero po rozważeniu alternatywnych rozwiązań. Obiekty Controller
reprezentują pewien aspekt procesu maszyny i działają niezależnie. Każdy kontroler musi mieć możliwość wykonywania zapytań o stan innych kontrolerów w dowolnym momencie, a każdy z nich zawiera prywatny vector<weak_ptr<Controller>>
do tego celu. Każdy wektor zawiera odwołanie cykliczne, 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) {
auto p = wp.lock();
if (p)
{
wcout << L"Status of " << p->Num << " = " << p->Status << endl;
}
else
{
wcout << L"Null object" << endl;
}
});
}
};
void RunTest()
{
vector<shared_ptr<Controller>> v{
make_shared<Controller>(0),
make_shared<Controller>(1),
make_shared<Controller>(2),
make_shared<Controller>(3),
make_shared<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);
}
Creating Controller0
Creating Controller1
Creating Controller2
Creating Controller3
Creating Controller4
push_back to v[0]: 1
push_back to v[0]: 2
push_back to v[0]: 3
push_back to v[0]: 4
push_back to v[1]: 0
push_back to v[1]: 2
push_back to v[1]: 3
push_back to v[1]: 4
push_back to v[2]: 0
push_back to v[2]: 1
push_back to v[2]: 3
push_back to v[2]: 4
push_back to v[3]: 0
push_back to v[3]: 1
push_back to v[3]: 2
push_back to v[3]: 4
push_back to v[4]: 0
push_back to v[4]: 1
push_back to v[4]: 2
push_back to v[4]: 3
use_count = 1
Status of 1 = On
Status of 2 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 2 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 2 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 2 = On
Status of 3 = On
Destroying Controller0
Destroying Controller1
Destroying Controller2
Destroying Controller3
Destroying Controller4
Press any key
W ramach eksperymentu zmodyfikuj wektor others
tak, aby był elementem vector<shared_ptr<Controller>>
, a następnie w danych wyjściowych zwróć uwagę, że podczas zwracania nie są wywoływane RunTest
żadne destruktory.
Zobacz też
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla