在包含共享指针列表的共享指针后面复制对象
copy object behind shared pointer containing a list of 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;
...
一棵树只需要给定一个 TreeNode 作为它的根。
Tree::Tree(const shared_ptr<TreeNode> root)
: root(root)
{}
因此,为了创建该子树,我尝试获取一个 TreeNode 并使用它调用 Tree 构造函数。
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
中任何 TreeNode 的父节点计算根节点时,我们将到达与 newTreeNode
不同的根节点,因为 newTreeNode
本身有一个父节点。
删除该父级不是解决方案,因为该对象是共享的,我们将在原始树中需要它。所以我看到的唯一解决方案是复制 TreeNode 并复制它的所有成员。
我该怎么做?
基于 SO 上的其他答案,我尝试了这个:
std::shared_ptr<TreeNode> TreeNode::clone() const
{
auto clone = new TreeNode (*this );
clone->setParent(weak_ptr<TreeNode>());
return shared_ptr<TreeNode>(clone);
}
但是还是计算父节点会导致原来的根节点。所以我无法创建子树。
我感觉Tree
和TreeNode
使用shared_ptr
是错误的,但这不是我的代码。我只需要添加一个功能。
您的克隆函数应该类似于:
std::shared_ptr<TreeNode> TreeNode::clone() const
{
auto res = std::make_shared<TreeNode>();
for (auto child : *children) {
res->AddChild(child->clone());
}
return res;
}
必须克隆整个子树,而不仅仅是子根。由于 none 的指针被复制,因此复制初始化克隆是没有用的。此外,您应该避免使用指向已分配内存的裸指针,以保证强大的异常安全性。
未经测试的示例:
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
我分享你的感受。当然,当节点有一个父指针时,不清楚如何在多棵树之间明智地共享节点。
std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>>
也显得过于间接了。
我有一个 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)
{}
因此,为了创建该子树,我尝试获取一个 TreeNode 并使用它调用 Tree 构造函数。
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
中任何 TreeNode 的父节点计算根节点时,我们将到达与 newTreeNode
不同的根节点,因为 newTreeNode
本身有一个父节点。
删除该父级不是解决方案,因为该对象是共享的,我们将在原始树中需要它。所以我看到的唯一解决方案是复制 TreeNode 并复制它的所有成员。
我该怎么做?
基于 SO 上的其他答案,我尝试了这个:
std::shared_ptr<TreeNode> TreeNode::clone() const
{
auto clone = new TreeNode (*this );
clone->setParent(weak_ptr<TreeNode>());
return shared_ptr<TreeNode>(clone);
}
但是还是计算父节点会导致原来的根节点。所以我无法创建子树。
我感觉Tree
和TreeNode
使用shared_ptr
是错误的,但这不是我的代码。我只需要添加一个功能。
您的克隆函数应该类似于:
std::shared_ptr<TreeNode> TreeNode::clone() const
{
auto res = std::make_shared<TreeNode>();
for (auto child : *children) {
res->AddChild(child->clone());
}
return res;
}
必须克隆整个子树,而不仅仅是子根。由于 none 的指针被复制,因此复制初始化克隆是没有用的。此外,您应该避免使用指向已分配内存的裸指针,以保证强大的异常安全性。
未经测试的示例:
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
forTree
andTreeNode
我分享你的感受。当然,当节点有一个父指针时,不清楚如何在多棵树之间明智地共享节点。
std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>>
也显得过于间接了。