저는 현재 스마트 포인터 사용법을 배우려고합니다. 그러나 몇 가지 실험을 수행하는 동안 포화 솔루션을 찾을 수없는 다음 상황을 발견했습니다.
클래스 A의 오브젝트가 클래스 B (자식)의 오브젝트의 상위가되지만 둘 다 서로를 알아야한다고 가정하십시오.
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
문제는 클래스 A의 객체가 어떻게 std::shared_ptr
자신의 ( this
)를 자식에게 전달할 수 있습니까?
Boost 공유 포인터 ( Getting a boost::shared_ptr
forthis
)에 대한 솔루션 이 있지만 std::
스마트 포인터를 사용하여이를 처리하는 방법은 무엇입니까?
답변
이 std::enable_shared_from_this
바로이 목적을 위해. 당신은 그것으로부터 상속하고 당신은 .shared_from_this()
클래스 내부에서 호출 할 수 있습니다 . 또한 여기에서 리소스 누출로 이어질 수있는 순환 종속성을 생성하고 있습니다. 이 문제는 std::weak_ptr
. 따라서 코드는 다음과 같이 보일 수 있습니다 (자녀가 부모의 존재에 의존하고 그 반대가 아니라고 가정).
class A;
class B;
class A
: public std::enable_shared_from_this<A>
{
public:
void addChild(std::shared_ptr<B> child)
{
children.push_back(child);
// like this
child->setParent(shared_from_this()); // ok
// ^^^^^^^^^^^^^^^^^^
}
private:
// note weak_ptr
std::list<std::weak_ptr<B>> children;
// ^^^^^^^^
};
class B
{
public:
void setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
}
private:
std::shared_ptr<A> parent;
};
그러나 그 부름은 .shared_from_this()
하려면 시점에서 this
소유 해야합니다 std::shared_ptr
. 이것은 더 이상 스택에 이러한 객체를 만들 수 없으며 일반적으로.shared_from_this()
생성자 또는 소멸자 내에서 호출 할 수 없음을 의미합니다 .
답변
스마트 포인터에 대한 오해에서 비롯된 것처럼 보이는 디자인에 몇 가지 문제가 있습니다.
스마트 포인터는 소유권을 선언하는 데 사용됩니다. 두 부모 모두 모든 자식을 소유하고 각 자식이 부모를 소유한다고 선언하여이를 깨뜨리는 것입니다. 둘 다 사실 일 수 없습니다.
또한 약한 포인터를 반환합니다. getChild()
. 이렇게하면 호출자가 소유권에 대해 신경 쓰지 않아야한다고 선언하는 것입니다. 이제 이것은 매우 제한적일 수 있지만 그렇게함으로써 약한 포인터가 여전히 유지되는 동안 문제의 자식이 파괴되지 않도록해야합니다. 스마트 포인터를 사용하면 자체적으로 정렬됩니다. .
그리고 마지막으로. 일반적으로 새 엔티티를 수락 할 때 일반적으로 원시 포인터를 수락해야합니다. 스마트 포인터는 부모간에 자식을 교체하는 자체 의미를 가질 수 있지만 일반적인 사용을 위해서는 원시 포인터를 허용해야합니다.