我会简单地更改树本身,然后处理它会更容易:
struct Node
{
Node(data_type data): mLeft(), mRight(), mData(data) {}
Node(const Node& rhs): mLeft(), mRight(), mData(rhs.mData)
{
if (rhs.mLeft.get()) mLeft.reset(new Node(*rhs.mLeft));
if (rhs.right.get()) mRight.reset(new Node(*rhs.mRight));
}
Node& operator=(Node rhs)
{
this->swap(rhs);
return *this;
}
~Node() { }
void swap(Node& rhs)
{
using std::swap;
swap(mLeft, rhs.mLeft);
swap(mRight, rhs.mRight);
swap(mData, rhs.mData);
}
Node* left() const { return mLeft.get(); }
void left(std::auto_ptr<Node> node) { mLeft= node; }
Node* right() const { return mRight.get(); }
void right(std::auto_ptr<Node> node) { mRight = node; }
data_type& data() { return mData; }
const data_type& data() const { return mData; }
private:
std::auto_ptr<Node> mLeft;
std::auto_ptr<Node> mRight;
data_type mData;
};
通过面向对象,每个节点现在负责它处理的内存。此外,std::auto_ptr
在界面中使用清楚地表明它需要所有权。
请注意,它是为深度复制、任何其他需要boost::shared_ptr
或等效的方法量身定制的。是std::auto_ptr
的,让您自己处理复制,那里没有魔法。
这种设计比使用C-struct
每个人都可以操纵资源的平原要干净得多。您仍然可以通过访问器完全访问底层数据......但他们注意不要调用未定义的行为......
当然,你仍然可以让它崩溃:
Node& node = ...
delete node.left(); // haha
但是,如果 C++ 可以防止意外问题,它就会为恶意代码敞开大门。