繁体   English   中英

std :: remove_if:从std :: vector中删除指针的所有出现

[英]std::remove_if: Removing all occurences of a pointer from std::vector

我有一个std :: vector实例,如下所示:

std::vector< std::pair<EndPointAddr*, EndPointAddr*>* > mServiceSubscriptionsList;

底层std :: pair对象中的第一项是订户实体的网络地址,而第二项是订阅实体的网络地址。 因此,std :: pair对象在此表示订阅作为订阅者和订阅端点地址对。

我想删除此向量中针对给定订户端点地址的所有订阅。 为此,我在下面写了指示函数,其中我使用带谓词的std :: remove_if。 根据std :: remove_if的文档,我的理解是std :: remove_if将所有出现的内容都删除到向量的末尾,并将向量的末尾向后移动到新的位置。

我的问题是:

如何在调用remove_if之后到达向量末尾的这些std :: pair项目,以便逐个动态地解除分配它们的内容(即解除对std :: pair *指针的攻击)? 你能在下面的功能代码中指出所需的代码片段吗? 我可以删除最后保留在迭代器中的第一个出现。 但是,我不知道如何删除其余的出现。 谢谢。

bool 
XXX::removeSubscriptionForASpecificSubscriber(EndPointAddr * ptrSubscriberAddr)
{
  auto last = 
       std::remove_if(mServiceSubscriptionsList.begin(),
                      mServiceSubscriptionsList.end(),
                      [ptrSubscriberAddr](std::pair<EndPointAddr*, EndPointAddr*>*  thePair) 
                      { 
                         return ptrSubscriberAddr->getXXXAddress().compareTo(thePair->first->getXXXAddress());
                      });

 if(last != mServiceSubscriptionsList.end())
 {

   //HERE I CAN DELET THE FIRST OCCURENCE, but WHAT I WANT IS TO DELETE ALL OCCURANCES
   if(*last != nullptr)
   { 
     delete *last;
   }

   mServiceSubscriptionsList.erase(last, mServiceSubscriptionsList.end());

   return true;
 }

 return false;
}

无法保证remove_if将已擦除的元素放在向量的末尾:范围[newEnd, oldEnd)中的迭代器是不可引用的,但元素具有未指定的值。

例如,以下代码

std::vector<int> v { 0, 1, 2, 3, 4 };
auto new_end = std::remove_if(v.begin(), v.end(), is_odd);

可以修改v包含它

0, 2, 4, 3, 4
         ^
       newEnd

您应该使用std::partition ,或者存储智能指针,以便您可以使用erase-remove习惯用法 (甚至根本不存储指针)。

该删除应该做什么? 最后..end包含'过时'元素垃圾,其内容被复制到它之前的向量。 当然你可以在ht lambda中使用delete调用一个for_each,但我怀疑这会得到明智的结果。

如果您想删除条目并删除其内容,则需要采用完全不同的方法。 就像制作原始指针unique_ptr一样。

如果我正确理解了文档 (“删除是通过移动范围中的元素以便覆盖要删除的元素来完成的”),则需要删除的元素将被覆盖,因此您无法删除其动态内容,因为您丢失指向要删除的元素的指针。

您应首先找到要移除的元素向量中的索引,取消分配它们,然后再进行删除。 我建议使用类似于此的解决方案:1)使用std::find_if查找要删除的第一个元素,2)释放内容并使用向量的“last”元素交换指针,3)重复直到std::find_if返回没有。 这里,“last”表示尚未标记为要删除的最后一个元素。

我将提供2个替代方案,而不是显示如何正确删除您的元素...

最佳解决方案:不要动态分配对:

std::vector<std::pair<EndPointAddr*, EndPointAddr*>>

很简单。 包含2个指针的一对很小。 动态分配该对会更快,更容易。 您也不必担心删除。

可接受的解决方案:使用unique_ptr

如果您知道动态分配的原因,并且知道在这种情况下必须使用智能指针( unique_ptr )。 unique_ptr将自行清理,因此您无需删除任何内容。

std::vector<std::unique_ptr<std::pair<EndPointAddr*, EndPointAddr*>>>

首先,写erase_remove_if

template<typename Container, typename Lambda>
Container&& erase_remove_if( Container&& c, Lambda&& closure ) {
  using std::begin; using std::end;
  auto new_end = std::remove_if( begin(c), end(c), std::forward<Lambda>(closure) );
  c.erase(new_end, end(c));
  return std::forward<Container>(c);
}

第二,擦除remove_if谓词中的数据:

bool removeSubscriptionForASpecificSubscriber(EndPointAddr * ptrSubscriberAddr)
{
  erase_remove_if( mServiceSubscriptionsList, 
    [ptrSubscriberAddr](std::pair<EndPointAddr*, EndPointAddr*>*  thePair) 
    {
      if (ptrSubscriberAddr->getXXXAddress().compareTo(thePair->first->getXXXAddress()))
      {
        delete ptrSubscriberAddr;
        return true;
      } else {
        return false;
      }
    });
  return true;
}

如果你不想使用std::unique_ptr存储你的指针对。 请注意,如果你有一个std::vector表示其中的指针的所有权,那么它实际上是一个几乎无痛的插入修复,使它成为一个vector<unique_ptr<>> 你必须删除一些管理内存的代码,用emplace_back替换一些push_back ,并添加一些.get()调用,以及它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM