容器迭代器失效(转)

一. 种类:程序员

  • 标准STL序列容器:vector、string、deque和list。
  • 标准STL关联容器:set、multiset、map和multimap。
  • 非标准序列容器slist和rope。slist是一个单向链表,rope本质上是一个重型字符串
  • 非标准关联容器hash_set、hash_multiset、hash_map和hash_multimap。
  • 几种标准非STL容器,包括数组、bitset、valarray、stack、queue和priority_queue

      值得注意的是,数组能够和STL算法配合,由于指针能够看成数组的迭代器使用算法

  二.删除元素
若是想删除东西,记住remove算法后,要加上erase
所谓删除算法,最终仍是要调用成员函数去删除某个元素,可是由于remove并不知道它如今做用于哪一个容器,因此remove算法不可能真的删除一个元素
1.Vector
 
复制代码
vector<int> v;   
v.reserve(10);   
for (int i = 1; i <= 10; ++i) {
 v.push_back(i);
}
cout << v.size();   // 10
v[3] = v[5] = v[9] = 99; 
remove(v.begin(), v.end(), 99); 
//v.erase(remove(v.begin(),v.end(),99),v.end());
cout << v.size();   // 10!
复制代码
2. list
list<int> listTest;
listTest.remove(99);//这个成员函数将真的删除元素,而且要比erase+remove高效
remove和remove_if之间的十分类似。但unique行为也像remove。它用来从一个区间删除东西(邻近的重复值)而不用访问持有区间元素的容器。若是你真的要从容器中删除元素,你也必须成对调用unique和erase,unique在list中也相似于remove。正像list::remove真的删除东西(并且比erase-remove惯用法高效得多)。list::unique也真的删除邻近的重复值(也比erase-unique高效)。
 
三 迭代器失效:
 
一个网友提的问题:
 

void   main() 

vector <string> vcs; 
vcs.push_back( "this   is   A "); 
vector <string   > ::iterator   it=vcs.begin(); 
int   i=9; 
for(;it!=vcs.end();++it) 

cout < < "caplity   of   vector   is   :   " < <vcs.size() < <endl; 

cout < < "---> " < <*it < <endl;   //去掉此句会有一个超过vector 
                                   //大小的循环,高手能解释一下为何? 
if(i==9) 

vcs.push_back( "this   is   BBBBB "); 
cout < < "vcs.push! " < <endl; 

i=8; 

}
典型的迭代器失效.
 
vector
1.当插入(push_back)一个元素后,end操做返回的迭代器确定失效。
2.当插入(push_back)一个元素后,capacity返回值与没有插入元素以前相比有改变,则须要从新加载整个容器,此时first和end操做返回的迭代器都会失效。
3.当进行删除操做(erase,pop_back)后,指向删除点的迭代器所有失效;指向删除点后面的元素的迭代器也将所有失效。
 
deque迭代器的失效状况:
1.在deque容器首部或者尾部插入元素不会使得任何迭代器失效。
2.在其首部或尾部删除元素则只会使指向被删除元素的迭代器失效。
3.在deque容器的任何其余位置的插入和删除操做将使指向该容器元素的全部迭代器失效。
List/set/map
1.删除时,指向该删除节点的迭代器失效
复制代码
list<int> intList; 
list<int>::iterator it = intList.begin(); 
while(it != intList.end()) 

it = intList.erase(it); 
…… 
}
复制代码
四.选择时机<转>--总结各类容器特色
(1) vector 内部数据结构:数组。 随机访问每一个元素,所须要的时间为常量。 在末尾增长或删除元素所需时间与元素数目无关,在中间或开头增长或删除元素所需时间随元素数目呈线性变化。 可动态增长或减小元素,内存管理自动完成,但程序员可使用reserve()成员函数来管理内存。 vector的迭代器在内存从新分配时将失效(它所指向的元素在该操做的先后再也不相同)。当把超过capacity()-size()个元素插入vector中时,内存会从新分配,全部的迭代器都将失效;不然,指向当前元素之后的任何元素的迭代器都将失效。当删除元素时,指向被删除元素之后的任何元素的迭代器都将失效。 (2)deque 内部数据结构:数组。 随机访问每一个元素,所须要的时间为常量。 在开头和末尾增长元素所需时间与元素数目无关,在中间增长或删除元素所需时间随元素数目呈线性变化。 可动态增长或减小元素,内存管理自动完成,不提供用于内存管理的成员函数。 增长任何元素都将使deque的迭代器失效。在deque的中间删除元素将使迭代器失效。在deque的头或尾删除元素时,只有指向该元素的迭代器失效。 (3)list 内部数据结构:双向环状链表。 不能随机访问一个元素。 可双向遍历。 在开头、末尾和中间任何地方增长或删除元素所需时间都为常量。 可动态增长或减小元素,内存管理自动完成。 增长任何元素都不会使迭代器失效。删除元素时,除了指向当前被删除元素的迭代器外,其它迭代器都不会失效。 (4)slist 内部数据结构:单向链表。 不可双向遍历,只能从前到后地遍历。 其它的特性同list类似。 (5)stack 适配器,它能够将任意类型的序列容器转换为一个堆栈,通常使用deque做为支持的序列容器。 元素只能后进先出(LIFO)。 不能遍历整个stack。 (6)queue 适配器,它能够将任意类型的序列容器转换为一个队列,通常使用deque做为支持的序列容器。 元素只能先进先出(FIFO)。 不能遍历整个queue。 (7)priority_queue 适配器,它能够将任意类型的序列容器转换为一个优先级队列,通常使用vector做为底层存储方式。 只能访问第一个元素,不能遍历整个priority_queue。 第一个元素始终是优先级最高的一个元素。 (8)set 键和值相等。 键惟一。 元素默认按升序排列。 若是迭代器所指向的元素被删除,则该迭代器失效。其它任何增长、删除元素的操做都不会使迭代器失效。 (9)multiset 键能够不惟一。 其它特色与set相同。 (10)hash_set 与set相比较,它里面的元素不必定是通过排序的,而是按照所用的hash函数分派的,它能提供更快的搜索速度(固然跟hash函数有关)。 其它特色与set相同。 (11)hash_multiset 键能够不惟一。 其它特色与hash_set相同。 (12)map 键惟一。 元素默认按键的升序排列。 若是迭代器所指向的元素被删除,则该迭代器失效。其它任何增长、删除元素的操做都不会使迭代器失效。 (13)multimap 键能够不惟一。 其它特色与map相同。 (14)hash_map 与map相比较,它里面的元素不必定是按键值排序的,而是按照所用的hash函数分派的,它能提供更快的搜索速度(固然也跟hash函数有关)。 其它特色与map相同。 (15)hash_multimap 键能够不惟一。 其它特色与hash_map相同。
相关文章
相关标签/搜索