容器迭代器失效(轉)

一. 種類:程序員

  • 標準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相同。
相關文章
相關標籤/搜索