c++ - Indicating (non) transfer of ownership with unique_ptr -
suppose have class this:
class node { public: node(node* parent = 0) : mparent(parent) {} virtual ~node() { for(auto p : mchildren) delete p; } // takes ownership void addchild(node* n); // returns object ownership node* firstchild() const; // not take ownership void setparent(node* n) { mparent = n; } // returns parent, not transfer ownership node* parent() const { return mparent; } private: list<node*> mchildren; node* mparent; }; i'd use smart pointers and/or rvalue references indicate ownership , isn't transferred.
my first guess change mchildren contain unique_ptrs, adapting function signatures follows.
// takes ownership void addchild(unique_ptr<node> n); // returns object ownership unique_ptr<node>& firstchild() const; // not take ownership void setparent(node* n) { mparent = n; } // returns parent, not transfer ownership node* parent() const { return mparent; } now, kind of problematic when need pass result of node::firstchild() function observes it, not take ownership, i'd need explicitly call .get() on unique_ptr, understand it, not recommended.
what correct , recommended way indicate ownership using unique_ptr without having resort using .get() , passing around bare pointers?
at first, use std::vector rather std::list contain children. unless have strong motivation not using it, std::vector should default container. if worried performance, don't be, because contiguous allocation done std::vector cause higher cache hit rate, speeding access enormously respect std::list, implies scattered allocation/access pattern.
secondly, correct in having std::vector<std::unique_ptr<node>> holding children, since reasonable assume node hold ownership of child nodes. other pointers except 1 accepted addchild(), on other hand, should non-owning raw pointers.
this applies mparent pointer , pointers returned node's member functions. in fact the, firstchild() member function return reference, throwing exception if node has no children. way create no confusion whatsoever owning returned object.
returning unique_ptr, or reference unique_ptr, not correct idiom: unique pointers represent ownership, , not want give ownership clients of node.
this how class like:
#include <vector> #include <memory> #include <stdexcept> class node { public: node() : mparent(nullptr) { } void addchild(std::unique_ptr<node>&& ptr) { mchildren.push_back(std::move(ptr)); ptr->setparent(this); } node& firstchild() const { if (mchildren.size() == 0) { throw std::logic_error("no children"); } else return *(mchildren[0].get()); } node& parent() const { if (mparent == nullptr) { throw std::logic_error("no parent"); } else return *mparent; } private: void setparent(node* n) { mparent = n; } std::vector<std::unique_ptr<node>> mchildren; node* mparent; }; you of course decide return non-owning, potentially null raw pointers instead of references if want avoid throwing exceptions. or add pair of hasparent() , getnumofchildren() methods retrieve information node's state. allow clients perform check if not want handle exceptions.
Comments
Post a Comment