std :: shared_ptr of this class A; class B; class A { public:

저는 현재 스마트 포인터 사용법을 배우려고합니다. 그러나 몇 가지 실험을 수행하는 동안 포화 솔루션을 찾을 수없는 다음 상황을 발견했습니다.

클래스 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_ptrforthis )에 대한 솔루션 이 있지만 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() . 이렇게하면 호출자가 소유권에 대해 신경 쓰지 않아야한다고 선언하는 것입니다. 이제 이것은 매우 제한적일 수 있지만 그렇게함으로써 약한 포인터가 여전히 유지되는 동안 문제의 자식이 파괴되지 않도록해야합니다. 스마트 포인터를 사용하면 자체적으로 정렬됩니다. .

그리고 마지막으로. 일반적으로 새 엔티티를 수락 할 때 일반적으로 원시 포인터를 수락해야합니다. 스마트 포인터는 부모간에 자식을 교체하는 자체 의미를 가질 수 있지만 일반적인 사용을 위해서는 원시 포인터를 허용해야합니다.


답변