[英]shared_ptr from unique_ptr of abstract class
我試圖遵循Herb Sutter的C ++指南,在這種情況下更喜歡unique_ptr
到原始指針和shared_ptr
。 支持std::unique_ptr
一個參數是在某些時候需要轉換為shared_ptr
。
在我的例子中,我有一個unique_ptr
的vector
,我需要傳遞給一個帶有shared_ptr
vector
的方法。 我希望能寫出類似的東西:
for (auto &uniquePtr : vectorUnique)
vectorShared.push_back(make_shared<Abstract>(move(uniquePtr));
這為我為基於Xcode 7.1
的C++11
工具鏈配置了以下錯誤:
錯誤:字段類型'Abstract'是一個抽象類。
當我使用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()
的調用,則可以將其推廣到更多容器。
我會這樣做:
for (auto &uniquePtr : vectorUnique) {
vectorShared.emplace_back(std::move(uniquePtr));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.