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将所有要删除的内容放到vector的末尾,并将vector的末尾向后移动到它的新位置。
我的问题是
我怎样才能到达这些std::pair项,在调用remove_if之后放入vector的末尾,以便逐个动态地释放它们的内容(即删除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
将擦除的元素放在vector的末尾:[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
,或者存储智能指针,以便您可以使用擦除-删除习惯用法(甚至根本不存储指针)。
这个删除应该做什么?最后..end包含"过时的"元素垃圾,其内容被复制到它之前的向量。当然,您可以在ht lambda中调用带有delete的范围上调用for_each,但我怀疑这会得到合理的结果。
如果您想要删除条目并删除其内容,则需要完全不同的方法。比如把原始指针改成unique_ptr
如果我正确理解了文档("删除是通过移动范围内的元素来完成的,要删除的元素被覆盖"),您需要删除的元素被覆盖,因此您无法删除其动态内容,因为您丢失了指向要删除的元素的指针。
您应该首先找到要删除的元素的vector中的下标,然后释放它们,然后再进行删除。我建议一个类似的解决方案:1)使用std::find_if
找到要删除的第一个元素,2)释放内容并与向量的"最后"元素交换指针,3)重复直到std::find_if
没有返回任何内容。这里,"last"是指最后一个尚未被标记为要删除的元素。
我将提供两种替代方法,而不是展示如何正确删除元素…
最佳解决方案:不要动态分配pair:
std::vector<std::pair<EndPointAddr*, EndPointAddr*>>
相当简单。包含两个指针的pair是很小的。而不是动态地分配那对会更快、更容易。你也不需要担心删除。
可接受的解决方案:使用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<>>
实际上是一个几乎没有痛苦的临时修复。您必须删除一些管理内存的代码,将一些push_back
替换为emplace_back
,并添加一些.get()
调用,然后它。
- 如何从 std::atomic 中提取指针 T<T>?
- std::vector::迭代器是否可以合法地作为指针
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 为什么这个 std::queue/指向结构的指针列表直到 List.Size() == 0 才释放内存?
- 如何调用存储在指向"std::函数"的指针中的 lambda?
- 如何使用 std::make_shared 创建基类类型的智能指针?
- 如何将唯一指针的 std::vector 转换为原始指针的 std::span?
- 编译器不会使用 -std=c++11 编译智能指针
- 我无法使用C++指针指向类方法返回的 std::vector
- std::byte 指针应该用于指针算术吗?
- std::unordered_map::提取引用/指针失效
- 在 c++ 中生成字符串到 std::指针列表的映射
- 通过线程共享 std::指针的矢量
- 将STD ::指针列表与比较器的对象列表
- std::指针和remove_if列表
- 调用具有const键类型引用的std::指针集的count方法
- 搜索指向类的std::指针集
- const传播到std::指针数组
- c++使用std::指针列表对std::vector元素重新排序
- 返回指向std::指针列表的指针时发生ImplicitCast_错误