[英]shared_ptr from unique_ptr of abstract class
I'm trying to follow Herb Sutter's C++ guidelines, in this case to prefer unique_ptr
to raw pointers and shared_ptr
. 我试图遵循Herb Sutter的C ++指南,在这种情况下更喜欢unique_ptr
到原始指针和shared_ptr
。 One of the arguments in favour of std::unique_ptr
is convertibility to shared_ptr
should that be needed at some point. 支持std::unique_ptr
一个参数是在某些时候需要转换为shared_ptr
。
In my case I have a vector
of unique_ptr
that I need to pass to a method that takes a vector
of shared_ptr
. 在我的例子中,我有一个unique_ptr
的vector
,我需要传递给一个带有shared_ptr
vector
的方法。 I was hoping to be able to write something like: 我希望能写出类似的东西:
for (auto &uniquePtr : vectorUnique)
vectorShared.push_back(make_shared<Abstract>(move(uniquePtr));
This gives me the following error with my Xcode 7.1
based toolchain configured for C++11
: 这为我为基于Xcode 7.1
的C++11
工具链配置了以下错误:
error: field type 'Abstract' is an abstract class. 错误:字段类型'Abstract'是一个抽象类。
It seems the STL is trying to hold a concrete instance of type Abstract
when I use make_shared
. 当我使用make_shared
时,似乎STL试图保持Abstract
类型的具体实例。 That would seem to make Mr. Sutter's advice unworkable in many cases, so I'm sure I must be doing something wrong! 这似乎使Sutter先生的建议在许多情况下变得不可行,所以我确信我一定做错了! I've resorted to writing: 我求助于写作:
for (auto &uniquePtr : vectorUnique) {
auto ptr = uniquePtr.get();
auto shared = shared_ptr<Abstract>(ptr);
vectorShared.push_back(shared);
uniquePtr.release();
}
Is there a better way to do this? 有一个更好的方法吗?
make_shared
constructs a new object using the given arguments and returns a shared_ptr
to it. make_shared
使用给定的参数构造一个新对象,并向其返回一个shared_ptr
。 So the compiler expects a constructor Abstract(std::unique_ptr<Abstract>)
, which is probably not what you have. 所以编译器需要一个构造函数Abstract(std::unique_ptr<Abstract>)
,这可能不是你拥有的。
What you want is the constructor of shared_ptr
that takes a unique_ptr
argument: 你想要的是shared_ptr
的构造函数,它接受一个unique_ptr
参数:
vectorShared.push_back(shared_ptr<Abstract>(move(uniquePtr)));
and, as it's not explicit
, then 而且,因为它不explicit
,那么
vectorShared.emplace_back(move(uniquePtr));
will just work (I've used emplace_back
to avoid redundant copying, at Richard Hodges's suggestion). 只会工作(我在Richard Hodges的建议中使用了emplace_back
来避免冗余复制)。 There's even a standard algorithm, so you don't need the for
loop: 甚至还有一个标准算法,所以你不需要for
循环:
std::move(vectorUnique.begin(), vectorUnique.end(),
std::back_inserter(vectorShared));
If you need this regularly, you might define a function: 如果您经常需要这个,您可以定义一个函数:
#include <vector>
#include <memory>
#include <algorithm>
template<typename T>
std::vector<std::shared_ptr<T>>
convert_to_shared(std::vector<std::unique_ptr<T>>&& vu)
{
using std::begin;
using std::end;
std::vector<std::shared_ptr<T>> vs;
vs.reserve(vu.size());
std::move(begin(vu), end(vu), std::back_inserter(vs));
return vs;
}
// Example of use
class Abstract {};
int main()
{
std::vector<std::unique_ptr<Abstract>> vectorUnique;
std::vector<std::shared_ptr<Abstract>> vectorShared
= convert_to_shared(std::move(vectorUnique));
}
Sorry about the terrible name (I'm open to suggestions). 抱歉这个可怕的名字(我愿意接受建议)。 If you omit the call to reserve()
, you could generalise it to more containers. 如果省略对reserve()
的调用,则可以将其推广到更多容器。
I would do it like this: 我会这样做:
for (auto &uniquePtr : vectorUnique) {
vectorShared.emplace_back(std::move(uniquePtr));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.