如何将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"));
}
我试过只使用 unique 而不是像那样共享:
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()
,但我不知道在哪里。
感谢您的帮助!
but i somehow get error-messages all over the place. Can someone explain how to get rid of the shared_ptrs?
unique_ptr
不可复制,只能移动。这意味着一旦你在 class 中放入一个 unique_ptr
成员,node
就不能再被复制:编译器为你生成的隐式复制赋值和构造函数将不会被复制还有了
所以你必须决定你希望你的class如何表现。
如果你想让你的 node
s 是可复制的,你必须自己实现复制操作(你必须深度克隆树)。这将为您提供价值语义。
否则,如果您不希望node
可复制,您仍然需要在构造函数中对node
对象执行深度克隆。原因是因为您正在传递 const
引用,所以您无法取得它们的内存所有权(并且您想要它们 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) {}
所以我正在尝试为二叉树构建一个模板 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"));
}
我试过只使用 unique 而不是像那样共享:
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()
,但我不知道在哪里。
感谢您的帮助!
but i somehow get error-messages all over the place. Can someone explain how to get rid of the shared_ptrs?
unique_ptr
不可复制,只能移动。这意味着一旦你在 class 中放入一个 unique_ptr
成员,node
就不能再被复制:编译器为你生成的隐式复制赋值和构造函数将不会被复制还有了
所以你必须决定你希望你的class如何表现。
如果你想让你的
node
s 是可复制的,你必须自己实现复制操作(你必须深度克隆树)。这将为您提供价值语义。否则,如果您不希望
node
可复制,您仍然需要在构造函数中对node
对象执行深度克隆。原因是因为您正在传递const
引用,所以您无法取得它们的内存所有权(并且您想要它们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) {}