using KnightRef = TSharedPtr<class Knight>;
class Knight : public RefCountable
{
public:
Knight()
{
cout << "Knight()" << endl;
}
~Knight()
{
cout << "~Knight()" << endl;
}
void SetTarget(KnightRef target)
{
_target = target;
}
private:
KnightRef _target = nullptr;
};
int main()
{
KnightRef k1(new Knight());
k1->ReleaseRef();
KnightRef k2(new Knight());
k2->ReleaseRef();
k1->SetTarget(k2);
k2->SetTarget(k1);
k1 = nullptr;
k2 = nullptr;
}
unique_ptr<Knight> k2 = make_unique<Knight>();
unique_ptr<Knight> k3 = k2; // 불가
unique_ptr<Knight> k3 = std::move(k2); // 이동을 해야지 복사가능
shared_ptr은 자작으로 만든 상속을 이용한 sharedptr과 다르게, RefCountable을 상속하는 것이 아니라 포인터로써 Count값을 가지고 있다. 그래서 따로 상속이 필요하지 않고, shared_ptr만을 이용하여 사용 할 수 있다. 즉, 클래스와 카운트에 해당하는 메모리 블록 두개를 할당하는 것이다.
shared_ptr<Knight> spr(new Knight());
shared_ptr<Knight> spr = make_shared<Knight>(); // new보다 우아한 방법
shared_ptr<Knight> spr2 = spr; // 복사
위크포인터는 반쪽짜리 스마트 포인터이다. 위에서 말한 RefCountingBlock은 두가지의 카운트 값을 가지고 있다고 했다.
해당 블록의 weakCount가 이 WeaKPtr에 의해서 값이 변동되게 할 수 있다. weakCount는 객체가 null이 될 때 값이 줄어 드는데, 이를 이용하여 Cycle문제를 해결 할 수 있다. 먼저 SharedPtr에 의해서 참조한 값이 0이 되지 않고, 사이클이 발생한다 했을 때 이 경우 RefCountBlock은 delete되지 않았을 것이다. 하지만 weakCount의값은 nullptr을 가리키고 있을 것이다. 이를 이용하여 해당 값이 nullptr인 경우 현재 사이클이 발생 중인 것을 알 수 있다.
shared_ptr<Knight> spr = make_shared<Knight>();
weak_ptr<Knight> wpr = spr;
bool expired = wpr.expired();
shared_ptr<Knight> spr2 = wpr.lock(); // 위와 현재 줄 두개는 사이클 해결방법