c++ stl里的vector::erase 和 map::erase 区别

转载于https://blog.csdn.net/feifeiiong/article/details/76572519

前言
关于这两者的区别和用法,网络上有很多五花八门的答案,有的还有很多错误,十分容易误导初学者。这里结合StackOverflow上的专家回答以及C++标准库来做一个简单的总结。

vector 与 map的区别
我们知道,vector是连续存储的数据结构,本质上是一个数组(指针确定数组的属性,如迭代器的起始和末尾,vector的size以及capacity等)。map是一个红黑树的数据结构,关于这部分的具体内容可以查看相关的标准库。因此,树形结构的map不是连续存储的。

函数功能
这两个函数都是从目标容器中删除指定元素,我们这里只讨论形参为迭代器类型的对应函数实现。

具体区别
首先,map与vector的erase都会产生返回值(C++11标准,C++98的map无返回值)。由我们已经预设的前提(函数形参为迭代器类型),erase操作都会返回一个指向被删除元素的下一个元素的迭代器(或者end()迭代器)。区别在于,vector的erase会破坏原有的数据存储(被删除元素的右侧元素整体向前移动),而map的erase则不会破坏树的完整结构,只是删除当前结点的元素。迭代器的本质都是指针,vector和map的erase都会使当前元素对应的迭代器失效,区别在于,vector的整个迭代器都会失效,而map只有当前被删除的元素迭代器失效。原因我们上面已经提过,是map和vector的内部实现不同造成。此外,SGI的文档中对map操作有这样的一句描述:Map has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements. Erasing an element from a map also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased. 
简单说,map的insert/erase操作都必须保证map的这样一个特性:这些操作不影响其它指向已存在元素的迭代器。

概念小结
首先,vector/map的erase操作都会使当前元素的迭代器失效,区别在于,vector会影响所有的存储元素,而map只会影响被删除的元素。 
其次,扩展到连续存储容器(queue)以及关联容器(set),都具备类似的性质。

使用范式
vector::erase
     vector iVec{1,3,3,4,5};
     auto it = iVec.begin();
     for(;it!=iVec.end();)
     {
         if(*it % 3 ==0)
             it=iVec.erase(it);    //删除元素,返回值指向已删除元素的下一个位置    
         else
             ++it;    //指向下一个位置
     }
1
2
3
4
5
6
7
8
9
注意到,我们在删除元素之后直接将返回值赋给it,这里绝对不能做自加操作,因为迭代器(后续)完全失效,这样的操作是未定义的。

map::erase
1.使用删除之前的迭代器定位下一个元素。
for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{
cout<first<<":"<second< mapTest.erase(iter++); // 这是与之前代码不同的地方 
}

2. erase() 成员函数返回下一个元素的迭代器
for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{
cout<first<<":"<second< iter=mapTest.erase(iter);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
这里给出两种写法,但更推荐的是第二种,因为在形式上与vector的写法基本一致,此外,第一种写法的理解关系到后置自增运算符的实现(先复制,再自增,后返回复制值),这种操作保证了iter迭代的有效性,同时,也体现了map::erase不影响之后元素的性质,更加贴近原理。如果把自增操作放在for循环内部,则是未定义的操作,因为此时iter迭代器已失效(元素被删除,指针已失效,无法自增)。
--------------------- 
 

你可能感兴趣的:(c/c++)