[摘要]本文是對STL--迭代器(iterator)的講解,對學習C++編程技術有所幫助,與大家分享。
原文:http://www.cnblogs.com/qunews/p/3761405.html
1 頭文件
所有容器有含有其各自的迭代器型別(iterator types),所以當你使用一般的容器迭代器時,並不需要含入專門的頭文件。不過有幾種特別的迭代器,例如逆向迭代器,被定義於<iterator>中。
2 迭代器類型
迭代器共分為五種,分別為: Input iterator、Output iterator、Forward iterator、Bidirectional iterator、Random access iterator。
迭代器iterator 提供了一種一般化的方法對順序或關聯容器類型中的每個元素進行連續訪問
2.1 Input(輸入)迭代器
只能一次一個向前讀取元素,按此順序一個個傳回元素值。表2.1列出了Input迭代器的各種操作行為。Input迭代器只能讀取元素一次,如果你復制Input迭代器,並使原Input迭代器與新產生的副本都向前讀取,可能會遍歷到不同的值。純粹Input迭代器的一個典型例子就是“從標准輸入裝置(通常為鍵盤)讀取數據”的迭代器。
-
表達式 功能表述
*iter 讀取實際元素
iter->member 讀取實際元素的成員(如果有的話)
++iter 向前步進(傳回新位置)
iter++ 向前步進(傳回舊位置)
iter1 == iter2 判斷兩個迭代器是否相同
iter1 != iter2 判斷兩個迭代器是否不相等
TYPE(iter) 復制迭代器(copy 構造函數)
2.2 Output(輸出)迭代器
Output迭代器和Input迭代器相反,其作用是將元素值一個個寫入。表2.2列出Output迭代器的有效操作。operator*只有在賦值語句的左手邊才有效。Output迭代器無需比較(comparison)操作。你無法檢驗Output迭代器是否有效,或“寫入動作”是否成功。你唯一可以做的就是寫入、寫入、再寫入。
-
表達式 功能表述
*iter = value 將元素寫入到迭代器所指位置
++iter 向前步進(傳回新位置)
iter++ 向前步進(傳回舊位置)
TYPE(iter) 復制迭代器(copy 構造函數)
2.3 Forward(前向)迭代器
Forward迭代器是Input迭代器與Output迭代器的結合,具有Input迭代器的全部功能和Output迭代器的大部分功能。表2.3總結了Forward迭代器的所有操作。Forward迭代器能多次指向同一群集中的同一元素,並能多次處理同一元素。
-
表達式 功能表述
*iter 存取實際元素
iter->member 存取實際元素的成員
++iter 向前步進(傳回新位置)
iter++ 向前步進(傳回舊位置)
iter1 == iter2 判斷兩個迭代器是否相同
iter1 != iter2 判斷兩個迭代器是否不相等
TYPE() 產生迭代器(default構造函數)
TYPE(iter) 復制迭代器(copy構造函數)
iter1 == iter2 復制
2.4 Bidirectional(雙向)迭代器
Bidirectional(雙向)迭代器在Forward迭代器的基礎上增加了回頭遍歷的能力。換言之,它支持遞減操作符,用以一步一步的后退操作。
2.5 Random Access(隨機存取)迭代器
Random Access迭代器在Bidirectional迭代器的基礎上再增加隨機存取能力。因此它必須提供“迭代器算數運算”(和一般指針“指針算術運算”相當)。也就是說,它能加減某個偏移量、能處理距離(differences)問題,並運用諸如<和>的相互關系操作符進行比較。以下對象和型別支持Random Access迭代器:
-
可隨機存取的容器(vector, deque)
-
strings(字符串,string,wstring)
-
一般array(指針)
3 迭代器相關輔助函數
3.1 advance() 令迭代器前進
3.2 distance() 處理迭代器之間的距離
3.3 iter_swap() 交換兩個迭代器所指內容
4 迭代器配接器
4.1 Reverse(逆向迭代器)
逆向迭代器重新定義遞增運算和遞減運算,使其行為正好倒置。成員函數rbegin()和rend()各傳回一個Reverse迭代器,和begin()和end()類似,共同定義一個半開區間。用正向迭代器可以直接構造一個逆向迭代器,但是構造之后會出現“錯位”現象。原因在逆向迭代器要保證半開區間不會越界,可調用逆向迭代器的base()函數,保證轉換值的正確性(迭代器移了一位)。
4.2 Insert(安插型)迭代器
Insert迭代器,也稱為inserters,用來將“賦值新值”操作轉換為“安插新值”操作。通過這種迭代器,算法可以執行安插(insert)行為而非覆蓋(overwrite)行為。所有Insert迭代器都隸屬於Output迭代器類型。所以它只提供賦值(assign)新值的能力。表4.2.1列出Insert迭代器的所有操作函數。
-
表達式 功能表述
*iter 無實際操作(傳回iter)
iter = value 安插value
++iter 無實際操作(傳回iter)
iter++ 無實際操作(傳回iter)
-
C++標准程序庫提供三種Insert迭代器:back inserters, front inserters, general inserters。它們的區別在於插入位置。事實上它們各自調用所屬容器中不同的成員函數。所以Insert迭代器初始化時要清楚知道自己所屬的容器是哪一種。表4.2.2列出Insert迭代器的種類。
-
名稱 Class 其所調用的函數 生成函數
Back inserter back_inserter_iterator push_back(value) back_inserter(cont)
Front inserter front_insert_iterator push_front(value) front_inserter(cont)
General inserter insert_iterator insert(pos, value) inserter(cont, pos)
4.3 Stream(流)迭代器
Stream迭代器是一種迭代器配接器,通過它,你可以把stream當成算法的原點和終點。更明確的說,一個istream迭代器可以用來從input stream中讀元素,而一個ostream迭代器可以用來對output stream寫入元素。
Stream迭代器的一種特殊形式是所謂的stream緩沖區迭代器,用來對stream緩沖區進行直接讀取和寫入操作。
Ostream迭代器
ostream迭代器 可以被賦予的值寫入output stream中。下表列出ostream迭代器的各項操作
-
-
算式 功能表述
ostream_iterator<T>(ostream) 為ostream產生一個ostream迭代器
ostream_iterator<T>(ostream, delim) 為ostream產生一個ostream迭代器,各元素間以delim為分隔符(請注意,delim的型別是const char*)
*iter 無實際操作(傳回iter)
iter = value 將value寫到ostream,像這樣:ostream<<value。其后再輸出一個delim(分隔符;如有定義的話)
++iter 無實際操作(傳回iter)
iter++ 無實際操作(傳回iter)
Istream迭代器
istream迭代器是ostream迭代器的拍檔,用來從input stream讀取元素。透過istream迭代器,算法可以從stream中直接讀取數據。istream迭代器的各項操作。
-
算式 功能表述
istream_iterator<T>() 產生一個end-of-stream迭代器
istream_iterator<T>(istream) 為istream產生的一個迭代器(可能立即去讀第一個元素)
*iter 傳回先前讀取的值(如果構造函數並未立刻讀取第一個元素值,則本式執行讀取任務)
iter->member 傳回先前讀取的元素的成員(如果有的話)
++iter 讀取下一個元素,並傳回其位置
iter++ 讀取下一個元素,並傳回迭代器指向前一個元素
iter1 == iter2 檢查iter1和iter2是否相等
iter1 != iter2 檢查iter1和iter2是否不相等
-
5.下面列舉了些例子說明各個容器的用法:
1、vector
#include <iostream>
#include <vector>
int main()
{
std::vector<char> charVector;
int x;
for (x=0; x<10; ++x)
charVector.push_back(65 + x);
int size = charVector.size();
for (x=0; x<size; ++x)
{
std::vector<char>::iterator start =
charVector.begin();
charVector.erase(start);
std::vector<char>::iterator iter;
for (iter = charVector.begin();
iter != charVector.end(); iter++)
{
std::cout << *iter;
}
std::cout << std::endl;
}
return 0;
}
2、deque
#include <iostream>
#include <deque>
int main()
{
std::deque<char> charDeque;
int x;
for (x=0; x<10; ++x)
charDeque.push_front(65 + x);
int size = charDeque.size();
for (x=0; x<size; ++x)
{
std::deque<char>::iterator start =
charDeque.begin();
charDeque.erase(start);
std::deque<char>::iterator iter;
for (iter = charDeque.begin();
iter != charDeque.end(); iter++)
{
std::cout << *iter;
}
std::cout << std::endl;
}
return 0;
}
3、list
#include <iostream>
#include <list>
int main()
{
// Create and populate the list.
int x;
std::list<char> charList;
for (x=0; x<10; ++x)
charList.push_front(65 + x);
// Display contents of list.
std::cout << "Original list: ";
std::list<char>::iterator iter;
for (iter = charList.begin();
iter != charList.end(); iter++)
{
std::cout << *iter;
//char ch = *iter;
//std::cout << ch;
}
std::cout << std::endl;
// Insert five Xs into the list.
std::list<char>::iterator start = charList.begin();
charList.insert(++start, 5, 'X');
// Display the result.
std::cout << "Resultant list: ";
for (iter = charList.begin();
iter != charList.end(); iter++)
{
std::cout << *iter;
//char ch = *iter;
//std::cout << ch;
}
return 0;
}
4、set
#include <iostream>
#include <set>
int main()
{
// Create the set object.
std::set<char> charSet;
// Populate the set with values.
charSet.insert('E');
charSet.insert('D');
charSet.insert('C');
charSet.insert('B');
charSet.insert('A');
// Display the contents of the set.
std::cout << "Contents of set: " << std::endl;
std::set<char>::iterator iter;
for (iter = charSet.begin(); iter != charSet.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Find the D.
iter = charSet.find('D');
if (iter == charSet.end())
std::cout << "Element not found.";
else
std::cout << "Element found: " << *iter;
return 0;
}
5、multiset
#include <iostream>
#include <set>
int main()
{
// Create the first set object.
std::multiset<char> charMultiset1;
// Populate the multiset with values.
charMultiset1.insert('E');
charMultiset1.insert('D');
charMultiset1.insert('C');
charMultiset1.insert('B');
charMultiset1.insert('A');
charMultiset1.insert('B');
charMultiset1.insert('D');
// Display the contents of the first multiset.
std::cout << "Contents of first multiset: " << std::endl;
std::multiset<char>::iterator iter;
for (iter = charMultiset1.begin();
iter != charMultiset1.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Create the second multiset object.
std::multiset<char> charMultiset2;
// Populate the multiset with values.
charMultiset2.insert('J');
charMultiset2.insert('I');
charMultiset2.insert('H');
charMultiset2.insert('G');
charMultiset2.insert('F');
charMultiset2.insert('G');
charMultiset2.insert('I');
// Display the contents of the second multiset.
std::cout << "Contents of second multiset: "
<< std::endl;
for (iter = charMultiset2.begin();
iter != charMultiset2.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Compare the sets.
if (charMultiset1 == charMultiset2)
std::cout << "set1 == set2";
else if (charMultiset1 < charMultiset2)
std::cout << "set1 < set2";
else if (charMultiset1 > charMultiset2)
std::cout << "set1 > set2";
return 0;
}
6、map
#include <iostream>
#include <map>
typedef std::map<int, char> MYMAP;
int main()
{
// Create the first map object.
MYMAP charMap1;
// Populate the first map with values.
charMap1[1] = 'A';
charMap1[4] = 'D';
charMap1[2] = 'B';
charMap1[5] = 'E';
charMap1[3] = 'C';
// Display the contents of the first map.
std::cout << "Contents of first map: " << std::endl;
MYMAP::iterator iter;
for (iter = charMap1.begin();
iter != charMap1.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Create the second map object.
MYMAP charMap2;
// Populate the first map with values.
charMap2[1] = 'F';
charMap2[4] = 'I';
charMap2[2] = 'G';
charMap2[5] = 'J';
charMap2[3] = 'H';
// Display the contents of the second map.
std::cout << "Contents of second map: " << std::endl;
for (iter = charMap2.begin();
iter != charMap2.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Compare the maps.
if (charMap1 == charMap2)
std::cout << "map1 == map2";
else if (charMap1 < charMap2)
std::cout << "map1 < map2";
else if (charMap1 > charMap2)
std::cout << "map1 > map2";
return 0;
}
7、multimap
#include <iostream>
#include <map>
typedef std::multimap<int, char> MYMAP;
int main()
{
// Create the first multimap object.
MYMAP charMultimap;
// Populate the multimap with values.
charMultimap.insert(MYMAP::value_type(1,'A'));
charMultimap.insert(MYMAP::value_type(4,'C'));
charMultimap.insert(MYMAP::value_type(2,'B'));
charMultimap.insert(MYMAP::value_type(7,'E'));
charMultimap.insert(MYMAP::value_type(5,'D'));
charMultimap.insert(MYMAP::value_type(3,'B'));
charMultimap.insert(MYMAP::value_type(6,'D'));
// Display the contents of the first multimap.
std::cout << "Contents of first multimap: " << std::endl;
MYMAP::iterator iter;
for (iter = charMultimap.begin();
iter != charMultimap.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Create the second multimap object.
MYMAP charMultimap2;
// Populate the second multimap with values.
charMultimap2.insert(MYMAP::value_type(1,'C'));
charMultimap2.insert(MYMAP::value_type(4,'F'));
charMultimap2.insert(MYMAP::value_type(2,'D'));
charMultimap2.insert(MYMAP::value_type(7,'E'));
charMultimap2.insert(MYMAP::value_type(5,'F'));
charMultimap2.insert(MYMAP::value_type(3,'E'));
charMultimap2.insert(MYMAP::value_type(6,'G'));
// Display the contents of the second multimap.
std::cout << "Contents of second multimap: " << std::endl;
for (iter = charMultimap2.begin();
iter != charMultimap2.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Compare the multimaps.
if (charMultimap == charMultimap2)
std::cout << "multimap1 == multimap2";
else if (charMultimap < charMultimap2)
std::cout << "multimap1 < multimap2";
else if (charMultimap > charMultimap2)
std::cout << "multimap1 > multimap2";
return 0;
}
8、stack
#include <iostream>
#include <list>
#include <stack>
int main()
{
std::stack<int, std::list<int> > intStack;
int x;
std::cout << "Values pushed onto stack:"
<< std::endl;
for (x=1; x<11; ++x)
{
intStack.push(x*100);
std::cout << x*100 << std::endl;
}
std::cout << "Values popped from stack:"
<< std::endl;
int size = intStack.size();
for (x=0; x<size; ++x)
{
std::cout << intStack.top() << std::endl;
intStack.pop();
}
return 0;
}
9、queue
#include <iostream>
#include <list>
#include <queue>
int main()
{
std::queue<int, std::list<int> > intQueue;
int x;
std::cout << "Values pushed onto queue:"
<< std::endl;
for (x=1; x<11; ++x)
{
intQueue.push(x*100);
std::cout << x*100 << std::endl;
}
std::cout << "Values removed from queue:"
<< std::endl;
int size = intQueue.size();
for (x=0; x<size; ++x)
{
std::cout << intQueue.front() << std::endl;
intQueue.pop();
}
return 0;
}
10、priority_queue
#include <iostream>
#include <list>
#include <queue>
int main()
{
std::priority_queue<int, std::vector<int>,std::greater<int> > intPQueue;
int x;
intPQueue.push(400);
intPQueue.push(100);
intPQueue.push(500);
intPQueue.push(300);
intPQueue.push(200);
std::cout << "Values removed from priority queue:"
<< std::endl;
int size = intPQueue.size();
for (x=0; x<size; ++x)
{
std::cout << intPQueue.top() << std::endl;
intPQueue.pop();
}
return 0;
}

