簡體   English   中英

如何從 std::shared_ptr 轉換為 std::unique_ptr?

[英]How to convert from std::shared_ptr to std::unique_ptr?

所以我正在嘗試為二叉樹構建模板 class 。 我有一種特殊的方式,我想用它來初始化樹(你可以在main()中看到)。

構造函數與shared_ptr一起工作得很好,但我想將它移動到更輕量級的unique_ptr ,但我不知何故得到了錯誤消息。 有人可以解釋如何擺脫 shared_ptrs 嗎? 這是帶有 shared_ptr 的工作版本:

#include <optional>
#include <memory>
#include <string>

template <class C>
class node{
private:
    C label;
    std::shared_ptr<node<C>> left;
    std::shared_ptr<node<C>> right;
public:
    node(const C& name,
            const std::optional<node<C>>& leftChild = {},
            const std::optional<node<C>>& rightChild = {}) : 
        label(name), 
        left(leftChild ? std::make_shared<node<C>>(*leftChild) : nullptr), 
        right(rightChild ? std::make_shared<node<C>>(*rightChild) : nullptr) {}
};

int main(){
    using sNode = node<std::string>;
    auto root = std::make_unique<sNode>("root", sNode("left", sNode("left.left")), sNode("right"));
}

我試圖只使用獨特的而不是這樣的共享:

template <class C>
class node{
private:
    C label;
    std::unique_ptr<node<C>> left;
    std::unique_ptr<node<C>> right;
public:
    node(const C& name,
            const std::optional<node<C>>& leftChild = {},
            const std::optional<node<C>>& rightChild = {}) : 
        label(name), 
        left(leftChild ? std::make_unique<node<C>>(*leftChild) : nullptr), 
        right(rightChild ? std::make_unique<node<C>>(*rightChild) : nullptr) {}
};

但是出現以下編譯錯誤:

In file included from /usr/include/c++/7/memory:80:0,
                 from binaryTree.hpp:2,
                 from main.cpp:1:
/usr/include/c++/7/bits/unique_ptr.h: In instantiation of ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = node<std::__cxx11::basic_string<char> >; _Args = {const node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<node<std::__cxx11::basic_string<char> >, std::default_delete<node<std::__cxx11::basic_string<char> > > >]’:
binaryTree.hpp:15:51:   required from ‘node<C>::node(const C&, const std::optional<node<C> >&, const std::optional<node<C> >&) [with C = std::__cxx11::basic_string<char>]’
main.cpp:7:80:   required from here
/usr/include/c++/7/bits/unique_ptr.h:825:30: error: use of deleted function ‘node<std::__cxx11::basic_string<char> >::node(const node<std::__cxx11::basic_string<char> >&)’
     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from main.cpp:1:0:
binaryTree.hpp:5:7: note: ‘node<std::__cxx11::basic_string<char> >::node(const node<std::__cxx11::basic_string<char> >&)’ is implicitly deleted because the default definition would be ill-formed:
 class node{
       ^~~~
binaryTree.hpp:5:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = node<std::__cxx11::basic_string<char> >; _Dp = std::default_delete<node<std::__cxx11::basic_string<char> > >]’
In file included from /usr/include/c++/7/memory:80:0,
                 from binaryTree.hpp:2,
                 from main.cpp:1:
/usr/include/c++/7/bits/unique_ptr.h:388:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^~~~~~~~~~
In file included from main.cpp:1:0:
binaryTree.hpp:5:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = node<std::__cxx11::basic_string<char> >; _Dp = std::default_delete<node<std::__cxx11::basic_string<char> > >]’
 class node{
       ^~~~
In file included from /usr/include/c++/7/memory:80:0,
                 from binaryTree.hpp:2,
                 from main.cpp:1:
/usr/include/c++/7/bits/unique_ptr.h:388:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^~~~~~~~~~

我想這與unique_ptr的已刪除分配運算符有關,我必須使用std::move() sonmewhere,但我不知道在哪里。 謝謝您的幫助!

但我不知何故到處都收到錯誤消息。 有人可以解釋如何擺脫 shared_ptrs 嗎?

unique_ptr不可復制,只能移動。 這意味着一旦您在 class 中放入unique_ptr成員, node就不能再被復制:編譯器為您生成的隱式復制分配和構造函數將不再存在。

所以你必須決定你希望你的 class 如何表現。

  • 如果您希望您的node是可復制的,您必須自己實現復制操作(您必須深度克隆樹)。 這將為您提供價值語義。

  • 否則,如果您不希望node可復制,您仍然需要在構造函數中執行node對象的深度克隆。 原因是,由於您正在傳遞const引用,因此您無法獲得它們的 memory 的所有權(並且您想要它們const因為您可能希望能夠傳遞臨時變量)。

  • 或者您可以更改您的界面以避免參考。 相反,采用接收器參數(即按值)並將它們移動到您的構造函數中。 (@rafix07 在答案中寫了這個,但現在被刪除了)。 您甚至可以對name參數執行此操作:

     node(C name, std::optional<node<C>> leftChild = {}, std::optional<node<C>> rightChild = {}): label(std::move(name)), left(leftChild? std::make_unique<node<C>>( std::move(*leftChild) ): nullptr), right(rightChild? std::make_unique<node<C>>( std::move(*rightChild) ): nullptr) {}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM