127

我目前正在尝试学习如何使用智能指针。然而,在做一些实验时,我发现了以下情况,我找不到令人满意的解决方案:

想象一下,您有一个 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自身的 a ( this) 传递给它的子对象?

有 Boost 共享指针(Getting a boost::shared_ptrforthis)的解决方案,但是如何使用std::智能指针来处理呢?

4

2 回答 2

202

就是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()从构造函数或析构函数中调用。

于 2012-07-29T16:54:43.957 回答
12

您的设计中有几个问题,这似乎源于您对智能指针的误解。

智能指针用于声明所有权。你通过声明父母都拥有所有孩子,而且每个孩子都拥有它的父母来打破这一点。两者都不可能是真的。

此外,您正在返回一个弱指针getChild()。通过这样做,您声明调用者不应该关心所有权。现在这可能是非常有限的,但通过这样做,您必须确保在仍然持有任何弱指针时所讨论的孩子不会被破坏,如果您使用智能指针,它会自行排序.

最后一件事。通常,当您接受新实体时,您通常应该接受原始指针。智能指针对于在父母之间交换孩子可以有自己的意义,但对于一般用途,您应该接受原始指针。

于 2012-07-29T16:57:38.480 回答