C++ 如何在std::copy算法中使用std::make\u move\u迭代器?

C++ 如何在std::copy算法中使用std::make\u move\u迭代器?,c++,stl,std,C++,Stl,Std,我有一个问题: 当我试图通过std::copy将数据从(vectorwithunique\u ptr)移动到(listwithunique\u ptr)时,算法成功地完成了,但在运行中会崩溃!下面是一个代码: std::向量向量字符串; std::unique_ptr ptrstringar1(新std::string(“qwe”); std::unique_ptr ptrStringArr2(新std::string(“asd”); vecUPTRstring.push_back(std::

我有一个问题:

当我试图通过
std::copy
将数据从(
vector
with
unique\u ptr
)移动到(
list
with
unique\u ptr
)时,算法成功地完成了,但在运行中会崩溃!下面是一个代码:


std::向量向量字符串;
std::unique_ptr ptrstringar1(新std::string(“qwe”);
std::unique_ptr ptrStringArr2(新std::string(“asd”);
vecUPTRstring.push_back(std::move(ptrstringar1));
vecUPTRstring.push_back(std::move(ptrstringar2));
std::list listUPTRstring;
std::copy(std::make_move_迭代器(vecUPTRstring.begin()),
std::make_move_迭代器(vecUPTRstring.end()),
std::make_move_迭代器(listUPTRstring.begin())
);
用于(自动变量:listUPTRstring(&V)
{
不能仅使源迭代器移动迭代器,而目标迭代器应该是插入器,因为列表为空。如果目标容器中已有
n
元素,并且希望用源元素覆盖它们,则只能将
dest.begin()
作为目标传递

std::copy(std::make_move_迭代器(vecUPTRstring.begin()),
std::make_move_迭代器(vecUPTRstring.end()),
std::inserter(listUPTRstring,listUPTRstring.end());
但是,我还必须建议使用移动迭代器代替
std::copy
,因为它更简单/更清晰:

std::move(vecUPTRstring.begin(),
vecUPTRstring.end(),
std::inserter(listUPTRstring,listUPTRstring.end());
只让源迭代器移动迭代器,而目标迭代器应该是插入器,因为列表是空的。如果目标容器中已有
n
元素,并且希望用源元素覆盖它们,则只能将
dest.begin()
作为目标传递

std::copy(std::make_move_迭代器(vecUPTRstring.begin()),
std::make_move_迭代器(vecUPTRstring.end()),
std::inserter(listUPTRstring,listUPTRstring.end());
但是,我还必须建议使用移动迭代器代替
std::copy
,因为它更简单/更清晰:

std::move(vecUPTRstring.begin(),
vecUPTRstring.end(),
std::inserter(listUPTRstring,listUPTRstring.end());

列表使用类似指针的间接方式保存值,并且在
std::list
中存储类似指针的小元素几乎比使用向量快得多,只有极少数例外。因此,首先,您应该检查使用
std::list
是否确实节省了您的时间。您还应该检查是否使用
std::unique_ptr可以为您节省任何时间

只有当基准测试证明使用这种间接寻址时性能得到改善时,才引入间接寻址。默认情况下,按值将内容保存在向量中。只有当测量结果显示有好处时,才使用其他容器和内存管理层。。我指的是测量结果。现代CPU的性能通常受内存访问模式的限制,而缓存未命中很容易淹没“浪费”复制连续缓存线的任何感知“开销”。第一种近似情况是,顺序内存访问是免费的

具体到字符串,以下类型的性能从最好到最差,最后一种非常糟糕,特别是当字符串很小时:

  • std::vector
  • std::vector
  • std::list
  • std::list
但是,如果您真的想使用列表,并在列表的后期执行大量的插入/删除操作(这是使用该数据类型的唯一原因),那么只需将值移动/复制到列表中一次,然后通过使用值而不是显式指针来享受低间接性的好处,成本可能会更低

在任何情况下,您都应该明确地对所有这些进行基准测试,因为在大多数情况下,
std::list
在没有缓存的微控制器上是有意义的,并且一旦您在大型应用程序的上下文中运行,并且在过去二十年的某个时候在PC类CPU上形成了一个活动堆,它就会变成一场性能灾难

template <typename T>
std::list<T> ptrVectorToList(std::vector<std::unique_ptr<T>> && src)
{
  std::list<T> list;
  for (auto &ptr : src) {
    list.emplace_back(std::move(*ptr));
    ptr.reset();
  }
  src.clear();
  return list;
}
模板
std::list ptrvectorList(std::vector&&src)
{
std::列表;
用于(自动和ptr:src){
列表。向后放置(标准::移动(*ptr));
ptr.reset();
}
src.clear();
退货清单;
}

列表使用类似指针的间接方式保存值,并且在
std::list
中存储类似指针的小元素几乎比使用向量快得多,只有极少数例外。因此,首先,您应该检查使用
std::list
是否确实节省了您的时间。您还应该检查是否使用
std::unique_ptr可以为您节省任何时间

只有当基准测试证明使用这种间接寻址时性能得到改善时,才引入间接寻址。默认情况下,按值将内容保存在向量中。只有当测量结果显示有好处时,才使用其他容器和内存管理层。。我指的是测量结果。现代CPU的性能通常受内存访问模式的限制,而缓存未命中很容易淹没“浪费”复制连续缓存线的任何感知“开销”。第一种近似情况是,顺序内存访问是免费的

具体到字符串,以下类型的性能从最好到最差,最后一种非常糟糕,特别是当字符串很小时:

  • std::vector
  • std::vector
  • std::list
  • std::list
但是如果你真的想使用一个列表,并且在列表的后期做了大量的插入/删除操作(这是使用该数据类型的唯一原因),那么在列表中移动/复制值的成本可能会更低
template <typename T>
std::list<T> ptrVectorToList(std::vector<std::unique_ptr<T>> && src)
{
  std::list<T> list;
  for (auto &ptr : src) {
    list.emplace_back(std::move(*ptr));
    ptr.reset();
  }
  src.clear();
  return list;
}