我试图遵循Herb Sutter的C ++指南,在这种情况下,更喜欢unique_ptr
到原始指针和shared_ptr
。赞成std::unique_ptr
的一个论点是,如果在某些时候需要,可转换为shared_ptr
。
在我的情况下,我有vector
unique_ptr
我需要传递给vector
shared_ptr
for (auto &uniquePtr : vectorUnique)
vectorShared.push_back(make_shared<Abstract>(move(uniquePtr));
的方法。我希望能够写出类似的内容:
Xcode 7.1
这为C++11
配置的基于Abstract
的工具链提供了以下错误:
错误:字段类型&#39;摘要&#39;是一个抽象的类。
当我使用make_shared
时,似乎STL正试图保留for (auto &uniquePtr : vectorUnique) {
auto ptr = uniquePtr.get();
auto shared = shared_ptr<Abstract>(ptr);
vectorShared.push_back(shared);
uniquePtr.release();
}
类型的具体实例。这似乎会使Sutter先生的建议在许多情况下变得不可行,所以我确定我一定做错了!我已经采取了写作:
#ifndef TEST_H
#define TEST_H
class test
{
public:
test();
};
#endif // TEST_H
有更好的方法吗?
答案 0 :(得分:7)
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));
将起作用(我已经使用emplace_back
来避免冗余复制,在Richard Hodges的建议中)。甚至还有标准算法,因此您不需要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()
的调用,则可以将其推广到更多容器。
答案 1 :(得分:2)
我会这样做:
for (auto &uniquePtr : vectorUnique) {
vectorShared.emplace_back(std::move(uniquePtr));
}