返回weak_ptr成员变量

问题描述 投票:0回答:1

我有以下TreeNode类,它可以存储对其父节点的引用以及指向其所有子节点的指针的向量。

TreeNode

class TreeNode : public std::enable_shared_from_this<TreeNode>
{
private:
    int val_;
    std::weak_ptr<TreeNode> parent_;
    std::vector<std::shared_ptr<TreeNode>> children_;
public:

    TreeNode(int val) : val_(val) {}

    void addChild(std::shared_ptr<TreeNode> child)
    {
        child->parent_ = shared_from_this();
        children_.push_back(std::move(child));
    }

    const int& getVal() const
    {
        return val_;
    }

    std::weak_ptr<TreeNode> getParent()
    {
        return parent_;
    }
};

parent_存储为weak_ptr,因此父级及其子级之间没有循环依赖项/内存泄漏。

Main

int main(int argc, char** argv) {
    std::shared_ptr<TreeNode> parent = std::make_shared<TreeNode>(1);
    std::shared_ptr<TreeNode> child = std::make_shared<TreeNode>(2);

    parent->addChild(child);

    // child->getParent()->getVal(); not possible
    return 0;
}

[使用此类时,我想访问任何节点的父级的值(...否则为什么要存储父级),但是由于parent_weak_ptr,因此我无法在其上调用任何成员函数。

[我知道周围有一些“骇客”,例如使用lockshared_ptr中提取weak_ptr,但是我觉得这使API变得笨拙。我想知道推荐的C ++ 11返回weak_ptr的方式是什么仍然可以使用。

编辑:

[我可能不应该将lock称为“ hack”,但从API的角度来看不太雅致。

例如,如果要访问parent_,则必须执行类似的操作

Main

if (!child->getParent()->expired())
{
    std::cout << child->getParent()->lock()->getVal() << std::endl;
}

这似乎很冗长,所以我想知道是否可以利用某些语言功能来避免做所有这些事情。

c++ c++11 shared-ptr smart-pointers
1个回答
1
投票

没有办法在lock上调用weak_ptrweak_ptr的全部要点是,它不会计入指向它所指向的对象的引用计数,同时仍然允许使用控制块检查对象是否有效,然后获取shared_ptr

对我来说,parent_不应是weak_ptr,而应是原始指针。使用原始指针不是一个坏习惯,也不是“不现代”,它们不应该拥有任何内存。这样,您就可以检查它是否为nullptr,以检查节点是否具有父级。

同样,您在lock上使用weak_ptr的示例是错误的。 shared_ptrweak_ptr可以由许多线程同时创建和销毁,因此它们是大多数用例所在的地方。

if (!child->getParent()->expired())
{
    std::cout << child->getParent()->lock()->getVal() << std::endl;
}

在您的示例中,您首先使用expired成员函数检查指针是否仍然有效,如果是,则使用lock获得将有助于对象引用计数的shared_ptr。如果有多个线程可能正在使用该指针,则在expired之后和lock调用之前,您的引用计数可能为0,并且可以从内存中删除对象。然后,您将从nullptr shared_ptr中获得一个lock,并在取消引用它时获得未定义的行为。

如果您继续使用weak_ptr,请这样做。

if(auto parent_ptr = child->getParent()->lock())
{
   // parent_ptr is shared_ptr that is not null here
}
© www.soinside.com 2019 - 2024. All rights reserved.