有没有比swap和pop更快的方法从std::vector中删除? 我问这个问题,其他相关问题似乎是针对C++版本的旧版本,不提及任何形式的并行化,或者集中在保持排序/索引与删除元素相同。

有没有比swap和pop更快的方法从std::vector中删除? 我问这个问题,其他相关问题似乎是针对C++版本的旧版本,不提及任何形式的并行化,或者集中在保持排序/索引与删除元素相同。,c++,stdvector,c++20,C++,Stdvector,C++20,我有一个可能包含数十万或数百万个元素的向量(这些元素是相当轻的结构,假设它们被压缩了大约20字节) 由于其他限制,它必须是std::vector,而其他容器将无法工作(如std::forward\u list),或者在其他用途中更不理想 最近,我从简单的it=std::erase(it)方法切换到使用pop和swap,使用如下内容: for(int i = 0; i < myVec.size();) { // Do calculations to determine if elemen

我有一个可能包含数十万或数百万个元素的向量(这些元素是相当轻的结构,假设它们被压缩了大约20字节)

由于其他限制,它必须是
std::vector
,而其他容器将无法工作(如
std::forward\u list
),或者在其他用途中更不理想

最近,我从简单的
it=std::erase(it)
方法切换到使用pop和swap,使用如下内容:

for(int i = 0; i < myVec.size();) {
  // Do calculations to determine if element must be removed
  // ...

  // Remove if needed
  if(elementMustBeRemoved) {
    myVec[i] = myVec.back();
    myVec.pop_back();
  } else {
    i++;
  }
}
auto firstToErase = std::remove_if(myVec.begin(), myVec.end(),
                                   [](const & T x){
                                   // Do calculations to determine if element must be removed
                                   // ...
                                   return elementMustBeRemoved;});
myVec.erase(firstToErase, myVec.end());
for(int i=0;i
这很有效,是一个显著的改进。它将该方法的运行时间缩短到以前的61%。但我想进一步改进这一点

< > C++有一种方法来有效地从<代码> STD::向量< /代码>中删除许多非连续元素吗?就像将索引向量传递给<代码> EraseEe()/Cuth>,并且在引擎盖下有C++做一些魔术来最小化数据的移动?

如果是这样的话,我可以让线程单独收集必须并行删除的索引,然后将它们合并并传递给erase()。

看看算法。您可以这样使用它:

for(int i = 0; i < myVec.size();) {
  // Do calculations to determine if element must be removed
  // ...

  // Remove if needed
  if(elementMustBeRemoved) {
    myVec[i] = myVec.back();
    myVec.pop_back();
  } else {
    i++;
  }
}
auto firstToErase = std::remove_if(myVec.begin(), myVec.end(),
                                   [](const & T x){
                                   // Do calculations to determine if element must be removed
                                   // ...
                                   return elementMustBeRemoved;});
myVec.erase(firstToErase, myVec.end());
cppreference指出,以下代码是remove_的可能实现,如果:

template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
   first = std::find_if(first, last, p);
   if (first != last)
       for(ForwardIt i = first; ++i != last; )
           if (!p(*i))
               *first++ = std::move(*i);
   return first;
}
模板
ForwardIt remove_if(ForwardIt first,ForwardIt last,一元谓词p)
{
first=std::find_if(first,last,p);
如果(第一个!=最后一个)
for(ForwardIt i=first;++i!=last;)
如果(!p(*i))
*第一个++=std::move(*i);
先返回;
}
它不与最后一个元素交换,而是不断地在容器中移动,形成一个应该擦除的元素范围,直到该范围位于向量的最末端。这看起来是一个更方便缓存的解决方案,您可能会注意到在一个非常大的向量上有一些性能改进

如果您想使用并行版本进行实验,那么有一个版本(4)允许指定执行策略。

看看算法。您可以这样使用它:

for(int i = 0; i < myVec.size();) {
  // Do calculations to determine if element must be removed
  // ...

  // Remove if needed
  if(elementMustBeRemoved) {
    myVec[i] = myVec.back();
    myVec.pop_back();
  } else {
    i++;
  }
}
auto firstToErase = std::remove_if(myVec.begin(), myVec.end(),
                                   [](const & T x){
                                   // Do calculations to determine if element must be removed
                                   // ...
                                   return elementMustBeRemoved;});
myVec.erase(firstToErase, myVec.end());
cppreference指出,以下代码是remove_的可能实现,如果:

template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
   first = std::find_if(first, last, p);
   if (first != last)
       for(ForwardIt i = first; ++i != last; )
           if (!p(*i))
               *first++ = std::move(*i);
   return first;
}
模板
ForwardIt remove_if(ForwardIt first,ForwardIt last,一元谓词p)
{
first=std::find_if(first,last,p);
如果(第一个!=最后一个)
for(ForwardIt i=first;++i!=last;)
如果(!p(*i))
*第一个++=std::move(*i);
先返回;
}
它不与最后一个元素交换,而是不断地在容器中移动,形成一个应该擦除的元素范围,直到该范围位于向量的最末端。这看起来是一个更方便缓存的解决方案,您可能会注意到在一个非常大的向量上有一些性能改进


如果您想尝试使用并行版本,有一个版本(4)允许指定执行策略。

或者,由于C++20,您可以稍微少键入一点并使用它。
但是,在这种情况下,您将失去选择执行策略的选项。

或者,由于C++20,您可以稍微减少键入并使用。 但是,在这种情况下,您将失去选择执行策略的选项

有没有比swap和pop更快的方法从std::vector中删除

自C++11以来,在不保留顺序的情况下从向量中删除单个元素的最佳方法是移动和弹出,而不是交换和弹出

C++有一种从STD::向量有效地去除许多非连续元素的方法?

remove-erase(C++20中的std::erase)是该标准提供的最有效的习惯用法<如果
确实保留了顺序,并且如果您不关心这一点,那么可能会有一种更有效的算法。但标准库并没有随附不稳定的“开箱即用”功能。算法如下:

  • 查找要删除的第一个元素(a)
  • 查找要删除的最后一个元素(b)
  • 把b移到a
  • 在a和b之间重复,直到迭代器相遇
有人建议将这种算法添加到标准库中,并且在中有一个演示实现

有没有比swap和pop更快的方法从std::vector中删除

自C++11以来,在不保留顺序的情况下从向量中删除单个元素的最佳方法是移动和弹出,而不是交换和弹出

C++有一种从STD::向量有效地去除许多非连续元素的方法?

remove-erase(C++20中的std::erase)是该标准提供的最有效的习惯用法<如果确实保留了顺序,并且如果您不关心这一点,那么可能会有一种更有效的算法。但标准库并没有随附不稳定的“开箱即用”功能。算法如下:

  • 查找要删除的第一个元素(a)
  • 查找要删除的最后一个元素(b)
  • 把b移到a
  • 在a和b之间重复,直到迭代器相遇

有人建议将这种算法添加到标准库中,在

中有一个演示实现,您可以自己制作。如果您事先知道元素的数量,您可以进行一些改进,例如使用单个resize()而不是几个pop_back()。根据多个因素,如擦除元素的密度和检查成本,使用原子,而不是循环另一个时间来删除元素。”比如将索引向量传递给