我有一个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;
}
答案 0 :(得分:5)
无法保证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 idiom(甚至根本不存储指针)。
答案 1 :(得分:2)
该删除应该做什么?最后..end包含'过时'元素垃圾,其内容被复制到它之前的向量。当然你可以在ht lambda中使用delete调用范围内的for_each,但我怀疑这会得到明智的结果。
如果您想删除条目并删除其内容,则需要采用完全不同的方法。就像改变原始指针unique_ptr一样。
答案 2 :(得分:2)
如果我理解正确documentation(“删除是通过移动范围内的元素来覆盖要删除的元素”),则需要删除的元素会被覆盖,所以你无法删除其动态内容,因为您丢失了要删除的元素的指针。
您应首先找到要移除的元素向量中的索引,取消分配它们,然后再删除它们。我建议使用类似于此的解决方案:1)使用std::find_if
查找要删除的第一个元素,2)释放内容并使用向量的“last”元素交换指针,3)重复直到{{1}没有回报。这里,“last”表示尚未标记为要删除的最后一个元素。
答案 3 :(得分:2)
我会提供两种选择,而不是展示如何正确删除你的元素......
最佳解决方案:不要动态分配货币对:
std::vector<std::pair<EndPointAddr*, EndPointAddr*>>
非常简单。包含2个指针的一对很小。 不动态分配该对将会更快,更容易。您也不必担心删除。
可接受的解决方案:使用unique_ptr
:
如果您知道动态分配的原因,并且知道在这种情况下必须使用智能指针(unique_ptr
)。 unique_ptr
将清理自己,因此您无需删除任何内容。
std::vector<std::unique_ptr<std::pair<EndPointAddr*, EndPointAddr*>>>
答案 4 :(得分:0)
首先,写下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<>>
。你必须删除一些管理内存的代码,用push_back
替换一些emplace_back
,然后添加一些.get()
个调用。