Ich würde einfach den Baum selbst ändern, wäre es einfacher, damit umzugehen, dann:
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;
};
Durch die objektorientierte, ist jeder Knoten nun verantwortlich für die Speicher es abwickelt. Auch die Verwendung std::auto_ptrin der Schnittstelle macht deutlich , dass es Eigentum nimmt.
Beachten Sie, dass es für Tief Kopieren zugeschnitten worden ist, anderer Ansatz erfordern boost::shared_ptroder gleichwertig. Und ja std::auto_ptrläßt Sie selbst mit dem Kopieren zu tun, es gibt keine Magie.
Dieser Entwurf ist viel sauberer als mit einer Ebene C-structmit allen , die Ressourcen manipulieren zu können. Sie haben noch vollen Zugriff auf die zugrunde liegenden Daten über die Accessor ... aber sie kümmern sich nicht undefiniert Verhalten aufzurufen ...
Natürlich kann man es immer noch abstürzen:
Node& node = ...
delete node.left(); // haha
Aber wenn C ++ gegen unbeabsichtigte Probleme schützen kann, läßt er die Tür offen zu bösem Code.