shared_ptr 来自 unique_ptr 的摘要 class
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));
我为 C++11
配置的基于 Xcode 7.1
的工具链出现以下错误:
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
使用给定的参数和 returns 一个 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));
}
我正在尝试遵循 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));
我为 C++11
配置的基于 Xcode 7.1
的工具链出现以下错误:
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
使用给定的参数和 returns 一个 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));
}