1、vector 的erase
看一下代码
#include<list>
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> ls;
ls.push_back(1);
ls.push_back(2);
ls.push_back(3);
vector<int>::iterator it = ls.begin();
for ( it = ls.begin(); it != ls.end();)
{
if (*it == 2)
{
ls.erase(it);
}
else
{
cout << *it << endl;
it++;
}
}
return 0;
}
当执行 ls.erase(it); 之后,迭代器it 已经失效,虽然他指向的地址是对的,但是此时,编译器已经把it当做一个失效的迭代器,此时你再对it进行++,程序将会崩溃,改成以下代码
it = ls.erase(it);
此时erase后会返回一个新的有效的迭代器
erase源码和简单分析如下
_CONSTEXPR20 iterator erase(const_iterator _Where) noexcept(
is_nothrow_move_assignable_v<value_type>) /* strengthened */ {
const pointer _Whereptr = _Where._Ptr;
auto& _My_data = _Mypair._Myval2;
pointer& _Mylast = _My_data._Mylast;
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(
_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr,
"vector erase iterator outside range");
#endif // _ITERATOR_DEBUG_LEVEL == 2
//移动Nxt指针
_Orphan_range(_Whereptr, _Mylast);
//将后面数据整体往前移动
_STD _Move_unchecked(_Whereptr + 1, _Mylast, _Whereptr);
//销毁最后一个节点
_Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1));
_ASAN_VECTOR_MODIFY(-1);
--_Mylast;
//返回一个新的迭代器
return iterator(_Whereptr, _STD addressof(_My_data));
}
综合以上正确的erase的用法如下
#include<list>
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> ls;
ls.push_back(1);
ls.push_back(2);
ls.push_back(3);
vector<int>::iterator it = ls.begin();
for ( it = ls.begin(); it != ls.end();)
{
if (*it == 2)
{
it= ls.erase(it);
}
else
{
cout << *it << endl;
it++;
}
}
return 0;
}