在BST中使用unique_ptr而不是shared_ptr

时间:2014-07-06 00:27:19

标签: c++ c++11 binary-search-tree shared-ptr unique-ptr

我正在尝试使用unique_ptr实施BST。我得到了shared_ptr的工作计划。如何使用unique_ptr来强制实施BinarySearchTree的单一所有权语义?

当我用shared_ptr替换unique_ptr时,我的编辑错误超出了我的理解范围。

#include <iostream>
#include <memory>

template<class T>
class BinarySearchTree{
    struct TreeNode;
    typedef std::shared_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)
{
    TreeNode *node = new TreeNode(ref);
    if (root==nullptr)
    {
        root.reset(node);
    }
    else
    {
        spTreeNode temp = root;
        spTreeNode prev = root;
        while (temp)
        {
            prev = temp;
            if (temp->data < ref)
                temp = temp->right;
            else
                temp = temp->left;
        }
        if (prev->data  < ref)
            prev->right.reset(node);
        else
            prev->left.reset(node);
    }
}

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

template<class T>
void BinarySearchTree<T>::print(const spTreeNode 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;
}

编辑:如果有人有兴趣,编译错误。警告:文字墙。

    prog.cpp: In instantiation of ‘void BinarySearchTree<T>::insert(const T&) [with T = int]’:
prog.cpp:75:18:   required from here
prog.cpp:39:27: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = BinarySearchTree<int>::TreeNode; _Dp = std::default_delete<BinarySearchTree<int>::TreeNode>]’
         spTreeNode temp = root;
                           ^
In file included from /usr/include/c++/4.8/memory:81:0,
                 from prog.cpp:2:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^
prog.cpp:40:27: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = BinarySearchTree<int>::TreeNode; _Dp = std::default_delete<BinarySearchTree<int>::TreeNode>]’
         spTreeNode prev = root;
                           ^
In file included from /usr/include/c++/4.8/memory:81:0,
                 from prog.cpp:2:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^
prog.cpp:43:18: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = BinarySearchTree<int>::TreeNode; _Dp = std::default_delete<BinarySearchTree<int>::TreeNode>]’
             prev = temp;
                  ^
In file included from /usr/include/c++/4.8/memory:81:0,
                 from prog.cpp:2:
/usr/include/c++/4.8/bits/unique_ptr.h:274:19: error: declared here
       unique_ptr& operator=(const unique_ptr&) = delete;
                   ^
prog.cpp:45:22: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = BinarySearchTree<int>::TreeNode; _Dp = std::default_delete<BinarySearchTree<int>::TreeNode>]’
                 temp = temp->right;
                      ^
In file included from /usr/include/c++/4.8/memory:81:0,
                 from prog.cpp:2:
/usr/include/c++/4.8/bits/unique_ptr.h:274:19: error: declared here
       unique_ptr& operator=(const unique_ptr&) = delete;
                   ^
prog.cpp:47:22: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = BinarySearchTree<int>::TreeNode; _Dp = std::default_delete<BinarySearchTree<int>::TreeNode>]’
                 temp = temp->left;
                      ^
In file included from /usr/include/c++/4.8/memory:81:0,
                 from prog.cpp:2:
/usr/include/c++/4.8/bits/unique_ptr.h:274:19: error: declared here
       unique_ptr& operator=(const unique_ptr&) = delete;
                   ^
prog.cpp: In instantiation of ‘void BinarySearchTree<T>::print() const [with T = int]’:
prog.cpp:79:15:   required from here
prog.cpp:59:15: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = BinarySearchTree<int>::TreeNode; _Dp = std::default_delete<BinarySearchTree<int>::TreeNode>]’
     print(root);
               ^
In file included from /usr/include/c++/4.8/memory:81:0,
                 from prog.cpp:2:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^
prog.cpp:63:6: error:   initializing argument 1 of ‘void BinarySearchTree<T>::print(BinarySearchTree<T>::spTreeNode) const [with T = int; BinarySearchTree<T>::spTreeNode = std::unique_ptr<BinarySearchTree<int>::TreeNode, std::default_delete<BinarySearchTree<int>::TreeNode> >]’
 void BinarySearchTree<T>::print(const spTreeNode node)const
          ^

2 个答案:

答案 0 :(得分:12)

unique_ptr不可分配但可移动。我重写了你的例子,现在使用unique_ptr s。请注意,我使用std::move将内容从一个unique_ptr移动到另一个unique_ptr。同样由于unique_ptr不可复制的事实,我通过引用而不是通过值传递成员函数中的#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; }

{{1}}

LIVE DEMO

答案 1 :(得分:3)

模板风格的错误总是很可怕,但不要惊慌!所有这些“使用已删除的功能”都是关于你试图复制unique_ptr,这使得它的超级大国不再是可移动的。跳转到每一行,并分析情况:

您是否希望转让指针的所有权?然后通过右值参考传递唯一指针并将其移动到新的持有者。

// 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 !
}

你只是想引用指针吗?使用对unique_ptr的const左值引用,或者从unique_ptr.get()传递一个const原始指针。

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

一旦完成所有这些操作,您将拥有编译代码,您将解决的其他错误,或者我将更新此答案。

注意:TreeNode *node = new TreeNode(ref);对异常安全感到嚎叫。你应该使用make_unique(来自C ++ 1y,或者自己制作)。

这是:

template <class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return unique_ptr<T>(new T(std::forward<Args>(args)...));
}