Should I move a unique_pointer or should I send a pointer to a unique_pointer?

喜你入骨 提交于 2019-12-11 20:31:46

问题


I am writing a c++ implementation of a BST tree using std::unique_ptr.

I am a hobbyist programmer. Initially, I wrote an insert function using a helper function and passing the pointer using move semantics, but that forced me to return unique_ptr. I then considered passing a pointer to the unique_ptr. I even considered using unique_ptr::get() and sending a pointer to the binaryNode, but I have read that this function should only be used when interfacing with legacy functions (Implementation not shown).

template<class K, class V = char>
struct binaryNode
{
    using nodePtr = std::unique_ptr<binaryNode<K, V>>;
    using keyType = K;
    using valueType = V;

    binaryNode(keyType key, valueType val) : _key(key), _value(val) {};
    binaryNode(const binaryNode& n) = delete;
    ~binaryNode() = default;

    keyType _key = keyType();
    valueType _value = valueType();
    nodePtr l_node = nullptr;
    nodePtr r_node = nullptr;
};

template<class K, class V = char>
class BSTree
{
public:
    using nodePtr = std::unique_ptr<binaryNode<K, V>>;
    using keyType = K;
    using valueType = V;

    BSTree() {}
    void insert(const keyType & key, const valueType & value);
    void insert2(const keyType & key, const valueType & value);

private:
    nodePtr insertHelper(nodePtr && root, const K & key, const V & value);
    void insertHelper2(nodePtr * root, const K & key, const V & value);

    nodePtr _root = nullptr;
};

template<class K, class V>
void BSTree<K, V>::insert(const keyType & key)
{
    _root = insertHelper(std::move(_root), key);
    if (!isBalanced(_root)) _root = rebalance(std::move(_root));
}

template<class K, class V>
typename BSTree<K, V>::nodePtr BSTree<K, V>::insertHelper(nodePtr && root, const keyType & key, const valueType & value)
{
    if (root == nullptr) return std::make_unique<binaryNode<K, V>>(std::move(binaryNode<K, V>(key)));

    if (key < root->_key) root->l_node = insertHelper(std::move(root->l_node), key, value);
    if (key > root->_key) root->r_node = insertHelper(std::move(root->r_node), key, value);

    return std::move(root);
}

template<class K, class V>
void BSTree<K, V>::insert2(const keyType & key, const valueType & value)
{
    insertHelper2(&_root, key, value);
    if (!isBalanced(_root)) _root = rebalance(std::move(_root));
}

template<class K, class V>
void BSTree<K, V>::insertHelper2(nodePtr * root, const K & key, const V & value)
{
    if (*root == nullptr) *root = std::make_unique<binaryNode<K, V>>(std::move(binaryNode<K, V>(key, value)));

    if (key < (*root)->_key) insertHelper(&((*root)->l_node), key, value);
    if (key > (*root)->_key) insertHelper(&((*root)->r_node), key, value);
}

Functionally, these two approaches give the same tree structures. I haven't tried timing the two approaches, but I am curious as to which of these approaches is considered "correct"? Or is there a better approach of which I have not thought?

EDIT: typos fixed

来源:https://stackoverflow.com/questions/54065699/should-i-move-a-unique-pointer-or-should-i-send-a-pointer-to-a-unique-pointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!