방법: weak_ptr 인스턴스 만들기 및 사용
경우에 따라 개체는 참조 수를 증가하지 않고 shared_ptr 기본 개체에 액세스하는 방법을 저장해야 합니다. 일반적으로 이 상황은 인스턴스 간에 shared_ptr
순환 참조가 있는 경우에 발생합니다.
최상의 디자인은 가능하면 언제든지 포인터의 공유 소유권을 방지하는 것입니다. 그러나 인스턴스의 shared_ptr
공유 소유권이 있어야 하는 경우 인스턴스 간에 순환 참조를 사용하지 않습니다. 순환 참조가 불가피하거나 어떤 이유로든 바람직한 경우 weak_ptr 사용하여 하나 이상의 소유자에게 다른 shared_ptr
소유자에 대한 약한 참조를 제공합니다. 를 weak_ptr
사용하여 기존 관련 인스턴스 집합에 조인하는 조인을 만들 수 있지만 기본 메모리 리소스가 여전히 유효한 경우에만 만들 shared_ptr
수 있습니다. 자체는 weak_ptr
참조 계산에 참여하지 않으므로 참조 수가 0으로 가는 것을 방지할 수 없습니다. 그러나 a를 weak_ptr
사용하여 초기화된 새 복사본을 shared_ptr
가져올 수 있습니다. 메모리가 이미 삭제weak_ptr
된 경우 's bool 연산자는 .false
메모리가 여전히 유효한 경우 새 공유 포인터는 참조 수를 증가시키고 변수가 범위에 유지되는 한 shared_ptr
메모리가 유효할 수 있도록 보장합니다.
예시
다음 코드 예제에서는 순환 종속성이 있는 weak_ptr
개체의 적절한 삭제를 보장하는 데 사용되는 경우를 보여줍니다. 예제를 검사할 때 대체 솔루션을 고려한 후에만 만들어진 것으로 가정합니다. 개체는 Controller
컴퓨터 프로세스의 일부 측면을 나타내며 독립적으로 작동합니다. 각 컨트롤러는 언제든지 다른 컨트롤러의 상태 쿼리할 수 있어야 하며 각 컨트롤러에는 이 목적을 위한 프라이빗 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) {
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
실험으로 벡터를 others
a vector<shared_ptr<Controller>>
로 수정한 다음 출력에서 반환될 때 RunTest
소멸자가 호출되지 않습니다.
참고 항목
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기