Using unique_ptr instead of shared_ptr in BST

浪尽此生 提交于 2019-12-01 08:33:19

unique_ptrs are not assignable but moveable. I reworked your example and now works with unique_ptrs. Notice, that I use std::move in order to move contents from one unique_ptr to another. Also due to the fact that unique_ptr isn't copyable, I pass unique_ptrs in member functions by reference and not by value:

#include <iostream>
#include <memory>

template<class T>
class BinarySearchTree{
    struct TreeNode;
    typedef std::unique_ptr<TreeNode> spTreeNode;
    struct TreeNode{
        T data;
        spTreeNode  left;
        spTreeNode  right;
        TreeNode(const T & value):data(value),left(nullptr),right(nullptr){}
    };



    spTreeNode root;
    bool insert(spTreeNode &node);
    void print(const spTreeNode&) const ;
public:
    BinarySearchTree();
    void insert( const T & node);
    void print()const;
};

template<class T>
BinarySearchTree<T>::BinarySearchTree():root(nullptr){}

template<class T>
void BinarySearchTree<T>::insert(const T & ref)
{
    std::unique_ptr<TreeNode> node(new TreeNode(ref));
    if (root == nullptr) {
        root = std::move(node);
    } else {
        TreeNode* temp = root.get();
        TreeNode* prev = root.get();
        while (temp != nullptr) {
            prev = temp;
            if (temp->data < ref)
                temp = temp->right.get();
            else
                temp = temp->left.get();
        }
        if (prev->data < ref)
            prev->right = std::move(node);
        else
            prev->left = std::move(node);
    }
}

template<class T>
void BinarySearchTree<T>::print()const
{
    print(root);
}

template<class T>
void BinarySearchTree<T>::print(const std::unique_ptr<TreeNode> &node) const
{
    if(node == nullptr) return;
    print(node->left);
    std::cout << node->data<< std::endl;
    print(node->right);
}

int main()
{
    BinarySearchTree<int> bst;
    bst.insert(13);
    bst.insert(3);
    bst.insert(5);
    bst.insert(31);
    bst.print();
    return 0;
}

LIVE DEMO

Template-flavored errors always tend to be horrible, but don't panic ! All these "use of deleted function" are about you trying to copy a unique_ptr, which gets its superpowers from being movable-only. Jump to each of these lines, and analyze the situation :

Do you wish to transfer ownership of the pointee ? Then pass the unique pointer by rvalue reference and move it to its new holder.

// Take unique_ptr by rvalue reference
void TreeNode::setLeft(std::unique_ptr<TreeNode> &&node) {
    // Move it in a member variable
    left = std::move(node);
    // Now it's ours !
}

Do you just wish to refer to the pointee ? Use a const lvalue reference to the unique_ptr, or pass a const raw pointer from unique_ptr.get().

// Take raw const pointer
bool isNodeLeft(TreeNode const *node) const {
    // Look at it but don't disturb it
    return node->value <= value;
}

Once all of these are out of the way, you'll either have a compiling code, some other error you'll resolve, or I'll update this answer.

Note : that TreeNode *node = new TreeNode(ref); is howling about exception safety. You should use make_unique (from C++1y, or craft your own).

Here it is :

template <class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!