Θα αλλάξει απλά το ίδιο το δέντρο, θα ήταν πιο εύκολο να ασχοληθεί με το θέμα, στη συνέχεια:
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;
};
Με το να είναι object-oriented, κάθε κόμβος είναι τώρα υπεύθυνη για τη μνήμη που χειρίζεται. Επίσης, χρησιμοποιώντας std::auto_ptrτο περιβάλλον εργασίας καθιστά σαφές ότι χρειάζεται ιδιοκτησίας.
Σημειώστε ότι είναι ήδη προσαρμοσμένο για βαθύ-αντιγραφή, οποιαδήποτε άλλη προσέγγιση που απαιτεί boost::shared_ptrή ισοδύναμο. Και ναι std::auto_ptrτα φύλλα σας που ασχολούνται με την αντιγραφή από τον εαυτό σας, δεν μαγεία εκεί.
Αυτό το σχέδιο είναι πολύ καθαρότερα από ό, τι χρησιμοποιώντας ένα απλό C-structμε όλους να είναι σε θέση να χειραγωγήσουν τους πόρους. Εξακολουθείτε να έχετε πλήρη πρόσβαση στις βασικές δεδομένων μέσω του εξαρτήματα, ... αλλά προσέξτε να μην επικαλούνται απροσδιόριστη συμπεριφορά ...
Φυσικά, μπορείτε ακόμα να διακοπεί η λειτουργία κάτω:
Node& node = ...
delete node.left(); // haha
Αλλά αν C ++ μπορεί να προστατεύσει από ακούσια θέματα, αφήνει την πόρτα ανοιχτή στο κακό κώδικα.