提问人:user11225404 提问时间:3/15/2023 最后编辑:Benjamin Buchuser11225404 更新时间:3/16/2023 访问量:269
如何制作shared_ptr的深度副本?
How to make deep a copy of shared_ptr?
问:
我有一个简单的节点树类。它是 的子类。 并且是对象。类是一个抽象类。 执行乘法的导数函数。MultNode
Node
_pRight
_pLeft
std::shared_ptr<Node>
Node
MultNode::DerFun()
Node
我必须创建临时的左右,我只需要使用智能指针。我不知道如何创建 的深层副本。Node(pTmpR and pTmpL)
shrared_ptr
void MultNode::DerFun() {
auto pTmpR = _pRight;
auto pTmpL = _pLeft;
_pRight->DerFun(); // sin(pi/4) * cos(pi/4);
_pLeft->DerFun(); // der(sin(pi/4) * cos(pi/4));
_pRight = std::make_shared<AddNode>(
std::make_shared<MultNode>(_pRight, pTmpL),
std::make_shared<MultNode>(pTmpR, _pLeft));
_pLeft = std::make_shared<NumNode>(1);
}
答:
4赞
Ahmed AEK
3/15/2023
#1
编译器无法通过指针进行深度复制,因为它不知道在编译时要复制什么。Derived
Base
解决方案是创建一个虚拟函数,该函数负责制作此派生对象的深拷贝,该函数将调用其所有子级来构造真正的深拷贝,并且由于它是在指针上调用的,因此将在运行时调用正确的函数。deepcopy
deepcopy
#include <memory>
class Node {
public:
virtual std::shared_ptr<Node> deepcopy() const = 0;
virtual ~Node() = default;
};
class MultNode: public Node {
private:
std::shared_ptr<Node> m_pleft;
std::shared_ptr<Node> m_pright;
public:
virtual std::shared_ptr<Node> deepcopy() const
{
return std::make_shared<MultNode>(m_pleft->deepcopy(), m_pright->deepcopy());
}
MultNode(std::shared_ptr<Node> pleft, std::shared_ptr<Node> pright) :
m_pleft(pleft), m_pright(pright) {};
};
3赞
n. m. could be an AI
3/15/2023
#2
根本没有必要深度复制任何内容。你有共享的指针,利用它们来发挥你的优势。
这是一个可以派生的最小系统。请注意,它生成的是 DAG,而不是树。一切都是,没有什么是永远不会改变的。节点尽可能共享。const
#include <memory>
class Node;
using NodePtr = std::shared_ptr<const Node>;
using Number = double;
class Node
{
public:
virtual ~Node() = default;
virtual NodePtr derive() const = 0;
};
class AddNode : public Node
{
public:
AddNode (const NodePtr& a, const NodePtr& b) : a(a), b(b) {}
private:
NodePtr a, b;
NodePtr derive() const override
{
return std::make_shared<AddNode>(a->derive(), b->derive());
}
};
class MultNode : public Node
{
public:
MultNode (const NodePtr& a, const NodePtr& b) : a(a), b(b) {}
private:
NodePtr a, b;
NodePtr derive() const override
{
const auto l = std::make_shared<MultNode>(a, b->derive());
const auto r = std::make_shared<MultNode>(a->derive(), b);
return std::make_shared<AddNode>(l, r);
}
};
class ConstNode : public Node
{
public:
ConstNode (Number v) : v(v) {}
private:
Number v;
NodePtr derive() const override
{
return std::make_shared<ConstNode>(Number{0});
}
};
class VarNode : public Node
{
public:
VarNode() {}
private:
NodePtr derive() const override
{
return std::make_shared<ConstNode>(Number{1});
}
};
警告:
- 没有经过太多测试
- 仅支持一个变量(易于更改)
- 缺少许多有用的节点,例如除法、函数组成、幂......(易于添加)
- 没有常量传播或其他简化表达式的方法(可以作为单独的方法添加)
评论
1赞
Caleth
3/15/2023
你甚至可以定义等NodePtr operator*(NodePtr l, NodePtr r) { return std::make_shared<MultNode>(l, r); }
0赞
sehe
3/15/2023
是的。这就是东西。Sean Parent® 批准了
0赞
sehe
3/15/2023
我只记得我过去也做过类似的评论,不举个例子就觉得很糟糕,所以这里是:stackoverflow.com/questions/27708139/transforming-trees-in-c/......
评论
*ptr
是由指针管理的对象MultNode
DerFun
void
Node
MultNode
AddNode
MultNode
AddNode
DerFun
const
p
std::make_shared<type>(*p);
* 1
+ 0