【问题标题】:Why does std::weak_ptr<T>::lock return empty shared pointer here?为什么 std::weak_ptr<T>::lock 在这里返回空共享指针?
【发布时间】:2021-09-01 13:39:55
【问题描述】:

我正在尝试创建一个 AABBTree 结构,其中每个节点都知道其父节点和子节点。

在我的AABBTreeNode 类中,父类存储为std::shared_ptr&lt;AABBTreeNode&gt;,子类存储为std::vector&lt;std::weak_ptr&lt;AABBTreeNode&gt;&gt;。 这样做是为了避免 Stackoverflow 帖子中指出的循环引用。

要添加一个新的孩子,我首先计算一个有效的边界框并调用以下函数:

void AABBTreeNode::AddChild(std::shared_ptr<open3d::geometry::AxisAlignedBoundingBox> partitionBound)
{
    auto child = std::make_shared<AABBTreeNode>(shared_from_this(), m_Mesh, partitionBound);
    m_Children.push_back(child);
}

调用此函数后,我想使用孩子 - 但是锁定函数总是返回一个空的std::shared_ptr&lt;T&gt;。这是调用代码(创建子代并用三角形填充它们应该递归完成):

void AABBTreeNode::AddTriangles(std::vector<Eigen::Vector3d>& centers)
{
    auto center = m_Bbox->GetCenter();
    for (auto& boundPoint : m_Bbox->GetBoxPoints())
    {
        // here is code, which calculates the minBound and maxBound for 
        // up to 8 Children

        auto adjustedPartitionBound = std::make_shared<open3d::geometry::AxisAlignedBoundingBox>(minBound, maxBound);
        AddChild(adjustedPartitionBound);
        auto child = m_Children.back().lock(); 
        if (child)
        {
            //this part is never reached, since child is alway empty...
            child->AddTriangles(partitionCenters);
        }
    }
}

为什么在这种情况下child 总是为空? 我试图只包含代码的重要部分,如果缺少某些信息,请告诉我。

【问题讨论】:

  • 刚刚注意到:一旦程序离开AddChild() 函数,m_Children.back().lock() 就会返回一个空指针。
  • 新创建节点的唯一所有者是AddChild中的child,当该所有者死亡时,该节点就消失了。
  • 我希望父母拥有自己的孩子,而不是相反。
  • @molbdnilo 正如我在下面的评论中提到的,你的意思是交换,使父成为弱指针,子成为智能指针?
  • 是的,但是将这些类型视为指针通常是有问题的(我个人不喜欢术语“智能指针”,因为它们都不是)。 shared_ptr 是“这个对象可以有一个或多个所有者,当没有人想要它时就消失了”,weak_ptr 是“我可以成为这个的所有者,如果当我想要它”。仔细想想,“父节点没有子节点就被销毁”似乎有点奇怪,但“子节点没有父节点就被销毁”就不是那么回事了。

标签: c++ smart-pointers weak-ptr


【解决方案1】:
{
    auto child = std::make_shared<AABBTreeNode>(shared_from_this(), m_Mesh, partitionBound);
    m_Children.push_back(child);
}

这里,自动变量child 是新创建节点的唯一所有者。在作用域结束时,child 被自动销毁,并且由于它是最后一个所有者,因此该节点也被销毁。

m_Children中的弱指针稍后被锁定时,由于指向的节点不再存在,结果是一个空的共享指针。

【讨论】:

  • 好的,这很有意义。所以解决方案是让它反过来吗?意味着父级应该是弱指针,子级应该是共享指针? (我想,这就是@molbdnilo 在上面的评论中指出的)
  • @RolandDeschain 是的,父母通常拥有它的孩子。在示例中您似乎没有父指针,但如果您确实为子代使用了共享所有权,那么您可以使用弱父指针。
猜你喜欢
  • 2011-06-15
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 2021-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多