Я бы просто изменить само дерево, было бы легче иметь дело с ним, то:
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 ++ может защитить от непредусмотренных проблем, он оставляет дверь открытой для злого кода.