C++ 移动标准::向量<;标准::唯一性\u ptr<;T>&燃气轮机;到std::vector<;标准::共享\u ptr<;T>&燃气轮机;
有时,我们会有一个工厂,它生成std::unique_ptr的向量,稍后我们会在类/线程/你所说的对象之间共享这些指针。因此,最好使用std::shared\u ptr。当然,有一种方法可以将std::uniqe_ptr转换为std::shared_ptrC++ 移动标准::向量<;标准::唯一性\u ptr<;T>&燃气轮机;到std::vector<;标准::共享\u ptr<;T>&燃气轮机;,c++,c++11,stl,c++14,C++,C++11,Stl,C++14,有时,我们会有一个工厂,它生成std::unique_ptr的向量,稍后我们会在类/线程/你所说的对象之间共享这些指针。因此,最好使用std::shared\u ptr。当然,有一种方法可以将std::uniqe_ptr转换为std::shared_ptr std::shared_ptr<int> sharedV; std::unique_ptr<int> uniqueV(new int(2)); sharedV = std::move(uniqueV); std::
std::shared_ptr<int> sharedV;
std::unique_ptr<int> uniqueV(new int(2));
sharedV = std::move(uniqueV);
std::shared_ptr sharedV;
标准:唯一(新国际(2));
sharedV=std::move(uniqueV);
那么,有没有直接的方法来处理std收集 您可以使用from
移动范围。它的行为很像std::copy
,但会移动。以下示例将所有unique\ptr
从uniqueV
移动到sharedV
uniqueV
的元素在示例末尾都将是nullptr
#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>
int main()
{
std::vector<std::shared_ptr<int>> sharedV;
std::vector<std::unique_ptr<int>> uniqueV;
uniqueV.emplace_back(std::make_unique<int>(42));
std::move(uniqueV.begin(), uniqueV.end(), std::back_inserter(sharedV));
return 0;
}
#包括
#包括
#包括
#包括
int main()
{
std::vectorsharedv;
std::向量uniqueV;
独特的安置(标准::使独特(42));
std::move(uniqueV.begin()、uniqueV.end()、std::back_inserter(sharedV));
返回0;
}
要添加到,std::vector有一个范围成员函数。仅仅将迭代器传递给unique_ptr
的向量是不起作用的,但是有一种方法可以将这些迭代器的解引用从左值转换为xvalues:及其相应的工厂函数:
这可能比使用std::back\u inserter
更有效的原因是insert()
预先知道结果大小,因此最多只需进行一次分配,然后实际插入不需要进行大小检查
写这篇文章太难了,我建议对这个名为extend()
的函数使用基于范围的重载:
因此,最好使用std::shared\u ptr,而不是这些东西是否需要参与所有权?如果没有,您可以通过引用传递向量。@NathanOliver对于某些特定情况,我们希望共享这些指针的所有权。不要过分热心:)会建议[令人沮丧的]更详细但也更有效的
sharedV.insert(sharedV.end(),std::make\u move\u迭代器(uniqueV.begin()),std::make\u move\u迭代器(uniqueV.end())
@Barry我不知道std::make\u move\u迭代器
。非常有趣。如果在我的答案后面附加这个解决方案,我会感到不舒服,我觉得它应该是一个明确的答案。好吧,如果你坚持:)我发现,首先调整目标向量的大小,然后只调整移动算法(或for循环)更具可读性。在这种情况下,这应该同样有效。实现者可以使用back\u inserter
进行同样的优化,对吗?@gmannickhow?通过添加每个算法的重载来获取输出迭代器?巴里:我想如果迭代器是随机访问迭代器,而输出迭代器是back\u插入器,那么实现可以额外检查back\u插入器中的容器是否可以reserve
,如果可以,调用reserve(std::distance(begin,end))
。然后像平常一样继续下去。这一切在编译时都应该是可行的。尽管仔细想想,move
的允许操作可能会完全禁止这种w.r.t异常。无需改变容量可能是不可取的。
sharedV.insert(sharedV.end(),
std::make_move_iterator(uniqueV.begin()),
std::make_move_iterator(uniqueV.end()));
template <class T, class Range>
void extend(std::vector<T>& dst, Range&& range) {
using std::begin; using std::end;
if constexpr (std::is_lvalue_reference<Range>{}) {
dst.insert(dst.end(), begin(range), end(range));
} else {
dst.insert(dst.end(),
std::move_iterator(begin(range)), std::move_iterator(end(range)));
}
}
extend(sharedV, std::move(uniqueV));