简体   繁体   English

复制包含共享指针列表的共享指针后面的对象

[英]copy object behind shared pointer containing a list of shared pointers

I have a shared_ptr<Tree> tree and a shared_ptr<TreeNode> node that contains a list of childrens as shared pointers. 我有一个shared_ptr<Tree> tree和一个shared_ptr<TreeNode> node ,其中包含作为共享指针的子项列表。

class TreeNode
{
protected:
    std::weak_ptr<TreeNode> parent;

    /**
    A list containing the children of this node
    */
    std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>> children;

   ...

A Tree needs only to be given a TreeNode as its root. 只需要给Tree一个TreeNode作为其根。

Tree::Tree(const shared_ptr<TreeNode> root)
    : root(root)
{}

So to create that sub Tree I try to get a TreeNode and call the Tree constructor with it. 因此,要创建该子树,我尝试获取一个TreeNode并使用它调用Tree构造函数。

shared_ptr<TreeNode> treeNode = oldTree->getASpecialNode();
shared_ptr<Tree> newTree = make_shared<Tree>(treeNode);

Now the root of newTree is treeNode . 现在, newTree的根是treeNode But the problem is, every TreeNode is pointing to its parent. 但是问题是,每个TreeNode都指向其父节点。 So does treeNode . treeNode

weak_ptr<TreeNode> TreeNode::getParent() const
{
    return parent;
}

When calculating the root by going through the parents of any TreeNode in newTree , we will reach a different root node than newTreeNode , because newTreeNode itself has a parent. 通过newTree中任何TreeNode的父级来计算根时,我们将获得与newTreeNode不同的根节点,因为newTreeNode本身具有父级。

Deleting that parent is no solution, because the object is shared and we will need it in the original Tree. 删除该父对象不是解决方案,因为该对象是共享的,我们将在原始Tree中使用它。 So the only solution I see is to copy the TreeNode and copy all it's members. 因此,我看到的唯一解决方案是复制TreeNode并复制其所有成员。

How can I do that? 我怎样才能做到这一点?

Based on other answers on SO I tried this: 基于SO的其他答案,我尝试了这个:

std::shared_ptr<TreeNode> TreeNode::clone() const
{
    auto clone = new TreeNode (*this );
    clone->setParent(weak_ptr<TreeNode>());
    return shared_ptr<TreeNode>(clone);
}

But still calculating the parents will lead to the original root node. 但是仍然计算父级将导致原始根节点。 So I wasn't able to create a sub tree. 因此,我无法创建子树。

I have the feeling that it's wrong to use shared_ptr for Tree and TreeNode , but it's not my code. 我感觉对TreeTreeNode使用shared_ptr是错误的,但这不是我的代码。 I just need to add a feature. 我只需要添加一个功能。

The entire subtree has to be cloned, not just the sub-root. 必须克隆整个子树,而不仅仅是子根。 Since none of the pointers are copied, it is not useful to copy initialize the clone. 由于没有指针被复制,因此复制初始化克隆没有用。 Also, you should avoid bare pointers to allocated memory in order to guarantee strong exception safety. 此外,您应避免使用裸指针指向已分配的内存,以确保强大的异常安全性。

Untested example: 未经测试的示例:

std::shared_ptr<TreeNode> TreeNode::clone() const
{
    auto clone = std::make_shared<TreeNode>();
    clone->children->reserve(children->size());
    for(const auto& c : *children) {
        auto c_clone = c->clone();
        c_clone->setParent(clone);
        clone->children->push_back(c_clone);
    }
    return clone;
}

I have the feeling that it's wrong to use shared_ptr for Tree and TreeNode 我觉得对TreeTreeNode使用shared_ptr是错误的

I share your feeling. 你的感觉 Certainly when the nodes have a parent pointer, it is unclear how the nodes could be sensibly shared across multiple trees. 当然,当节点具有父指针时,不清楚如何在多个树之间合理地共享节点。

std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>> also seems excessive indirection. std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>>也似乎是过多的间接std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>>

Your clone function should look like something like: 您的克隆函数应类似于:

std::shared_ptr<TreeNode> TreeNode::clone() const
{
    auto res = std::make_shared<TreeNode>();

    for (auto child : *children) {
        res->AddChild(child->clone());
    }
    return res;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM