复制包含共享指针列表的共享指针后面的对象
问题描述:
我有一个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;
...
树只需要被赋予一个TreeNode作为它的根。
Tree::Tree(const shared_ptr<TreeNode> root)
: root(root)
{}
所以创建子树我试图让一个树节点,并调用树构造它。
shared_ptr<TreeNode> treeNode = oldTree->getASpecialNode();
shared_ptr<Tree> newTree = make_shared<Tree>(treeNode);
现在的newTree
根源是treeNode
。但问题是,每个TreeNode都指向它的父节点。那么treeNode
。
weak_ptr<TreeNode> TreeNode::getParent() const
{
return parent;
}
当在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);
}
但仍在计算的父母会导致原来的根节点。所以我无法创建一个子树。
我的感觉是shared_ptr
用于Tree
和TreeNode
,但它不是我的代码。我只需要添加一个功能。
答
的整个子树已被克隆,而不仅仅是子根。由于没有任何指针被复制,所以复制初始化克隆没有用处。另外,为了保证强大的异常安全性,您应该避免使用裸指针分配内存。
未经测试的例子:
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;
}
我有一个是错误的使用
shared_ptr
为Tree
和TreeNode
我份额你的感觉的感觉。当然,当节点具有父指针时,不清楚如何在多棵树上合理地共享节点。
std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>>
也似乎过度间接。
答
你的克隆功能看起来应该是这样的:
std::shared_ptr<TreeNode> TreeNode::clone() const
{
auto res = std::make_shared<TreeNode>();
for (auto child : *children) {
res->AddChild(child->clone());
}
return res;
}
您的克隆应执行深层复制:创建一个新节点并克隆每个孩子。 – Jarod42
由于您的标题包含“复制”这个词,因此您迄今为止的答案已经相当合理地假设您想要一个副本。在其他情况下,子树也可以指由一些现有节点组成的树(如现有树的过滤版本)。这种子树将从共享的指向儿童矢量的指针中受益。所以这就是它使用共享指针的原因,但如果这不是要求,那么我会同意shared_ptrs看起来很奇怪。 – ROX
我想我更喜欢那种子树。但是我会遇到父母的问题。代码节点中的某处需要通过父节点遍历。然后可以转到原始根节点。 – Sadik