我正在尝试遵循 Herb Sutter 的 C++ 指南,在这种情况下,我更喜欢 unique_ptr
而不是原始指针和 shared_ptr
。支持 std::unique_ptr
的论点之一是在某些时候需要时可以转换为 shared_ptr
。
在我的例子中,我有一个 vector
的 unique_ptr
我需要传递给一个方法,该方法采用 shared_ptr 的
。我希望能够写出类似这样的东西:vector
for (auto &uniquePtr : vectorUnique)
vectorShared.push_back(make_shared<Abstract>(move(uniquePtr));
这为我的 Xcode 7.1
配置了 C++11
的工具链带来了以下错误:
error: field type 'Abstract' is an abstract class.
当我使用 make_shared
时,STL 似乎试图保存类型为 Abstract
的具体实例。在许多情况下,这似乎会使 Sutter 先生的建议行不通,所以我确定我一定做错了什么!我求助于写作:
for (auto &uniquePtr : vectorUnique) {
auto ptr = uniquePtr.get();
auto shared = shared_ptr<Abstract>(ptr);
vectorShared.push_back(shared);
uniquePtr.release();
}
有更好的方法吗?
最佳答案
make_shared
使用给定的参数构造一个新对象并返回一个 shared_ptr
给它。所以编译器需要一个构造函数 Abstract(std::unique_ptr<Abstract>)
,这可能不是您拥有的。
你想要的是shared_ptr
的构造函数这需要 unique_ptr
参数:
vectorShared.push_back(shared_ptr<Abstract>(move(uniquePtr)));
而且,因为它不是 explicit
, 然后
vectorShared.emplace_back(move(uniquePtr));
将正常工作(根据 Richard Hodges 的建议,我使用 emplace_back
来避免冗余复制)。甚至还有一个标准算法,因此您不需要 for
循环:
std::move(vectorUnique.begin(), vectorUnique.end(),
std::back_inserter(vectorShared));
如果你经常需要这个,你可以定义一个函数:
#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));
}
抱歉这个糟糕的名字(我愿意接受建议)。如果您省略对 reserve()
的调用,您可以将其推广到更多容器。
关于c++ - 来自抽象类的 unique_ptr 的 shared_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34163186/