C语言完成STL中的erase函数,C++ STL中erase()函数使用陷阱

21d05c505d1c1f1ae251c8fb9c2672b6.png

一  陷阱现象描述

最近在项目中需要实现一个超时数据自动删除功能,采用了deque这个数据结构使用它的头删尾插功能。在实现删除功能时,程序出现了crash。

程序在iOS平台上未出现异常现象,但是在Android平台偶尔会出现crash现象。通过ndk-stack 定位堆栈,发现是crash在下面这个地方。

52856ba406c225b677619ad5baccb090.png

仔细分析这里的item是一个deque结构 m_naks的迭代器(it)的引用,只是对变量执行自增,并没有其它复杂逻辑。那么为什么会crash在这个地方呢?再有一种可能那就是item是个非法的迭代器自增在写内存的时候出现crash。m_naks只存在push_back()、pop_front()、erase ()这些操作,前面两种不会出现非法的内存访问现象,只有这个erase (it ++)可能出现问题。

二 现象原因分析

经过查看相关资料发现对于vector、deque这类序列式容器其内部数据结构是一个数组,在使用erase ()函数时需要注意一下几点。

vector的迭代器在内存重新分配时将失效(它所指向的元素在该操作的前后不再相同)。当把超过capacity()-size()个元素插入vector中时,内存会重新分配,所有的迭代器都将失效;否则,指向当前元素以后的任何元素的迭代器都将失效。当删除元素时,指向被删除元素以后的任何元素的迭代器都将失效。

增加任何元素都将使deque的迭代器失效。在deque的中间删除元素将使迭代器失效。在deque的头或尾删除元素时,只有指向该元素的迭代器失效。

deque内存结构示意图

b44402a5894639d1cb6ac54995004d90.png

内存地址均为假设仅用于表示连续的内存地址空间,如果要删除it指向的这片空间deque的内存结构将发生变化,所以在删除时执行it++,将导致it指向下一个内存空间,但是erase()执行完毕之后,deque的内存结构已经发生变化。此时it将指向一个未知的空间,必定会导致程序出现crash现象。

三 原因总结

1 所以上述迭代器的正确删除方式如下:

6eddabf99be468c57e40ba1b9568544f.png

调用erase函数之后,将它的返回值赋给it。

2 对于关联容器map、set、multimap、multiset、list,这些数据结构在删除当前迭代器时,不会使当前迭代器失效(因为这些迭代器底层实现上,并非使用连续内存空间,而是使用了红黑树、链)。

3 对于vector、deque 这2种数据结构的迭代器,删除操作将导致当前迭代器失效,注意合理使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值