c++smart-pointersweak-ptr

Why does std::weak_ptr<T>::lock return empty shared pointer here?


I'm trying to create an AABBTree structure where each node knows its parent and children.

Within my AABBTreeNode class, the parent is stored as a std::shared_ptr<AABBTreeNode> and the children as a std::vector<std::weak_ptr<AABBTreeNode>>. This is done to avoid circular references as pointed out in this Stackoverflow post.

To add a new child I first calculate a valid bounding box and call the following function:

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);
}

After calling this function, I want to use the child - however the lock function always returns an empty std::shared_ptr<T>. Here is the calling code (Creating Children and filling them with triangles should be done recoursively):

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);
        }
    }
}

Why is child always empty in this case? I tried to include only important parts of the code, let me know if some information is missing.


Solution

  • {
        auto child = std::make_shared<AABBTreeNode>(shared_from_this(), m_Mesh, partitionBound);
        m_Children.push_back(child);
    }
    

    Here, the automatic variable child is the sole owner of the newly created node. At the end of the scope, child is automatically destroyed, and as it is the last owner, the node is destroyed as well.

    When the weak pointer in m_Children is locked later, the result is an empty shared pointer since the pointed node no longer exists.