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

C++ 复制包含共享指针列表的共享指针后面的对象,c++,c++11,shared-ptr,deep-copy,C++,C++11,Shared Ptr,Deep Copy,我有一个shared_ptr树和一个shared_ptr节点,其中包含作为共享指针的子节点列表 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>

我有一个
shared_ptr树
和一个
shared_ptr节点
,其中包含作为共享指针的子节点列表

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;

   ...
当通过遍历
newTree
中任何树节点的父节点来计算根节点时,我们将到达与
newTreeNode
不同的根节点,因为
newTreeNode
本身有一个父节点

删除该父对象不是解决方案,因为该对象是共享的,我们需要在原始树中使用它。所以我看到的唯一解决方案是复制TreeNode并复制它的所有成员

我该怎么做

基于上的其他答案,我尝试了以下方法:

std::shared_ptr<TreeNode> TreeNode::clone() const
{
    auto clone = new TreeNode (*this );
    clone->setParent(weak_ptr<TreeNode>());
    return shared_ptr<TreeNode>(clone);
}
std::shared_ptr TreeNode::clone()常量
{
自动克隆=新树节点(*此);
克隆->设置父对象(弱_ptr());
返回共享的ptr(克隆);
}
但是仍然计算父节点将导致原始根节点。所以我无法创建一个子树


我觉得对
树和
树节点使用
shared\u ptr
是错误的,但这不是我的代码。我只需要添加一个功能

您的克隆函数应该类似于:

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

    for (auto child : *children) {
        res->AddChild(child->clone());
    }
    return res;
}
std::shared_ptr TreeNode::clone()常量
{
auto res=std::make_shared();
用于(自动子项:*子项){
res->AddChild(child->clone());
}
返回res;
}

必须克隆整个子树,而不仅仅是子根。由于没有复制任何指针,因此复制并初始化克隆是没有用的。此外,为了保证强异常安全,您应该避免指向已分配内存的裸指针

未经测试的示例:

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;
}
std::shared_ptr TreeNode::clone()常量
{
自动克隆=标准::使_共享();
克隆->子对象->保留(子对象->大小());
适用于(const auto&c:*儿童){
自动克隆=c->clone();
c_clone->setParent(克隆);
克隆->子对象->推回(c_克隆);
}
返回克隆;
}

我觉得对
树和
树节点使用
shared\u ptr
是错误的

我同意你的感受。当然,当节点有父指针时,不清楚如何在多个树上合理地共享节点


std::shared\u ptr
似乎也太间接了。

你的克隆人应该做一个深度复制:创建一个新节点,克隆每个子节点。由于你的标题中包含“复制”一词,到目前为止,你的答案相当合理地假设你想要一个副本。在其他情况下,子树也可以指由一些现有节点组成的树(如现有树的过滤版本)。这种子树将受益于指向子向量的共享指针。这就是使用共享指针的原因,但如果这不是一个要求,那么我同意共享指针看起来很奇怪。我想我更喜欢这种子树。但我对父母的事有意见。代码中的某个地方需要遍历父节点。然后一个将转到原始根节点。您忘记设置新子节点的父节点。
std::shared_ptr<TreeNode> TreeNode::clone() const
{
    auto clone = new TreeNode (*this );
    clone->setParent(weak_ptr<TreeNode>());
    return shared_ptr<TreeNode>(clone);
}
std::shared_ptr<TreeNode> TreeNode::clone() const
{
    auto res = std::make_shared<TreeNode>();

    for (auto child : *children) {
        res->AddChild(child->clone());
    }
    return res;
}
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;
}