日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ STL与迭代器

發布時間:2023/12/13 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ STL与迭代器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

將容器類模板實例化時,會指明容器中存放的元素是什么類型的:可以存放基本類型的變量,也可以存放對象。

對象或基本類型的變量被插入容器中時,實際插入的是對象或變量的一個復制品。

STL 中的許多算法(即函數模板),如排序、查找等算法,在執行過程中會對容器中的元素進行比較。這些算法在比較元素是否相等時通常用運算符進行,比較大小通常用<運算符進行,因此,被放入容器的對象所屬的類最好重載==和<運算符,以使得兩個對象用==和<進行比較是有定義的。

順序容器

順序容器有以下三種:可變長動態數組 vector、雙端隊列 deque、雙向鏈表 list。
它們之所以被稱為順序容器,是因為元素在容器中的位置同元素的值無關,即容器不是排序的。

關聯容器

關聯容器有以下四種:set、multiset、map、multimap。關聯容器內的元素是排序的。插入元素時,容器會按一定的排序規則將元素放到適當的位置上,因此插入元素時不能指定位置。
默認情況下,關聯容器中的元素是從小到大排序(或按關鍵字從小到大排序)的,而且用<運算符比較元素或關鍵字大小。因為是排好序的,所以關聯容器在查找時具有非常好的性能。

棧/隊列
除了以上兩類容器外,STL 還在兩類容器的基礎上屏蔽一部分功能,突出或增加另一部分功能,實現了三種容器適配器:棧 stack、隊列 queue、優先級隊列 priority_queue。


概述


容器都是類模板。它們實例化后就成為容器類。用容器類定義的對象稱為容器對象。

例如,vector<int>是一個容器類的名字,vector<int> a;就定義了一個容器對象 a,a 代表一個長度可變的數組,數組中的每個元素都是 int 類型的變量;

任何兩個容器對象,只要它們的類型相同,就可以用 <、<=、>、>=、==、!= 進行詞典式的比較運算。假設 a、b 是兩個類型相同的容器對象,這些運算符的運算規則如下。

  • a == b:若 a 和 b 中的元素個數相同,且對應元素均相等,則a == b的值為 true,否則值為 false。元素是否相等是用==運算符進行判斷的。
  • a<b:規則類似于詞典中兩個單詞比較大小,從頭到尾依次比較每個元素,如果發生 a 中的元素小于 b 中的元素的情況,則a<b的值為 true;如果沒有發生 b 中的元素小于 a 中的元素的情況,且 a 中的元素個數比 b 少,a<b的值也為 true;其他情況下值為 false。元素比較大小是通過<運算符進行的。
  • a > b:等價于 b < a。

?

所有容器都有以下兩個成員函數:

  • int size():返回容器對象中元素的個數。
  • bool empty():判斷容器對象是否為空。


順序容器和關聯容器還有以下成員函數:

  • begin():返回指向容器中第一個元素的迭代器。
  • end():返回指向容器中最后一個元素后面的位置的迭代器。
  • rbegin():返回指向容器中最后一個元素的反向迭代器。
  • rend():返回指向容器中第一個元素前面的位置的反向迭代器。
  • erase(...):從容器中刪除一個或幾個元素。該函數參數較復雜,此處省略。
  • clear():從容器中刪除所有元素。


如果一個容器是空的,則 begin() 和 end() 的返回值相等,rbegin() 和 rend() 的返回值也相等。

順序容器還有以下常用成員函數:

  • front():返回容器中第一個元素的引用。
  • back():返回容器中最后一個元素的引用。
  • push_back():在容器末尾增加新元素。
  • pop_back():刪除容器末尾的元素。
  • insert(...):插入一個或多個元素。該函數參數較復雜,此處省略。

?

迭代器(iterator)

?

要訪問順序容器和關聯容器中的元素,需要通過“迭代器(iterator)”進行。迭代器是一個變量,相當于容器和操縱容器的算法之間的中介。迭代器可以指向容器中的某個元素,通過迭代器就可以讀寫它指向的元素。從這一點上看,迭代器和指針類似
1) 正向迭代器,定義方法如下:容器類名::iterator? 迭代器名;
2) 反向迭代器,定義方法如下:容器類名::reverse_iterator? 迭代器名;

#include <iostream> #include <vector> using namespace std; int main() {vector<int> v; //v是存放int類型變量的可變長數組,開始時沒有元素for (int n = 0; n<5; ++n)v.push_back(n); //push_back成員函數在vector容器尾部添加一個元素vector<int>::iterator i; //定義正向迭代器for (i = v.begin(); i != v.end(); ++i) { //用迭代器遍歷容器cout << *i << " "; //*i 就是迭代器i指向的元素*i *= 2; //每個元素變為原來的2倍}cout << endl;//用反向迭代器遍歷容器for (vector<int>::reverse_iterator j = v.rbegin(); j != v.rend(); ++j)cout << *j << " ";return 0; }

程序的輸出結果是:
0 1 2 3 4
8 6 4 2 0

第 6 行,vector 容器有多個構造函數,如果用無參構造函數初始化,則容器一開始是空的。

第 10 行,begin 成員函數返回指向容器中第一個元素的迭代器。++i 使得 i 指向容器中的下一個元素。end 成員函數返回的不是指向最后一個元素的迭代器,而是指向最后一個元素后面的位置的迭代器,因此循環的終止條件是i != v.end()。

第 16 行定義了反向迭代器用以遍歷容器。反向迭代器進行++操作后,會指向容器中的上一個元素。rbegin 成員函數返回指向容器中最后一個元素的迭代器,rend 成員函數返回指向容器中第一個元素前面的位置的迭代器,因此本循環實際上是從后往前遍歷整個數組。

如果迭代器指向了容器中最后一個元素的后面或第一個元素的前面,再通過該迭代器訪問元素,就有可能導致程序崩潰,這和訪問 NULL 或未初始化的指針指向的地方類似。

不同容器的迭代器的功能

1) 正向迭代器。假設 p 是一個正向迭代器,則 p 支持以下操作:++p,p++,*p。此外,兩個正向迭代器可以互相賦值,還可以用==和!=運算符進行比較。

2) 雙向迭代器。雙向迭代器具有正向迭代器的全部功能。除此之外,若 p 是一個雙向迭代器,則--p和p--都是有定義的。--p使得 p 朝和++p相反的方向移動。

3) 隨機訪問迭代器。隨機訪問迭代器具有雙向迭代器的全部功能。若 p 是一個隨機訪問迭代器,i 是一個整型變量或常量,則 p 還支持以下操作:

  • p+=i:使得 p 往后移動 i 個元素。
  • p-=i:使得 p 往前移動 i 個元素。
  • p+i:返回 p 后面第 i 個元素的迭代器。
  • p-i:返回 p 前面第 i 個元素的迭代器。
  • p[i]:返回 p 后面第 i 個元素的引用。


此外,兩個隨機訪問迭代器 p1、p2 還可以用 <、>、<=、>= 運算符進行比較。p1<p2的含義是:p1 經過若干次(至少一次)++操作后,就會等于 p2。其他比較方式的含義與此類似。

對于兩個隨機訪問迭代器 p1、p2,表達式p2-p1也是有定義的,其返回值是 p2 所指向元素和 p1 所指向元素的序號之差(也可以說是 p2 和 p1 之間的元素個數減一)。

下面的程序中,每個循環演示了一種做法。

#include <iostream> #include <vector> using namespace std; int main() {vector<int> v(100); //v被初始化成有100個元素for(int i = 0;i < v.size() ; ++i) //size返回元素個數cout << v[i]; //像普通數組一樣使用vector容器vector<int>::iterator i;for(i = v.begin(); i != v.end (); ++i) //用 != 比較兩個迭代器cout << * i;for(i = v.begin(); i < v.end ();++i) //用 < 比較兩個迭代器cout << * i;i = v.begin();while(i < v.end()) { //間隔一個輸出cout << * i;i += 2; // 隨機訪問迭代器支持 "+= 整數" 的操作} }

迭代器的輔助函數

STL 中有用于操作迭代器的三個函數模板,它們是:

  • advance(p, n):使迭代器 p 向前或向后移動 n 個元素。
  • distance(p, q):計算兩個迭代器之間的距離,即迭代器 p 經過多少次 + + 操作后和迭代器 q 相等。如果調用時 p 已經指向 q 的后面,則這個函數會陷入死循環。
  • iter_swap(p, q):用于交換兩個迭代器 p、q 指向的值。

下面的程序演示了這三個函數模板的 用法。

#include <list> #include <iostream> #include <algorithm> //要使用操作迭代器的函數模板,需要包含此文件 using namespace std; int main() {int a[5] = { 1, 2, 3, 4, 5 };list <int> lst(a, a+5);list <int>::iterator p = lst.begin();advance(p, 2); //p向后移動兩個元素,指向3cout << "1)" << *p << endl; //輸出 1)3advance(p, -1); //p向前移動一個元素,指向2cout << "2)" << *p << endl; //輸出 2)2list<int>::iterator q = lst.end();q--; //q 指向 5cout << "3)" << distance(p, q) << endl; //輸出 3)3iter_swap(p, q); //交換 2 和 5cout << "4)";for (p = lst.begin(); p != lst.end(); ++p)cout << *p << " ";return 0; }

程序的輸出結果是:
1) 3
2) 2
3) 3
4) 1 5 3 4 2

?

STL中“大”、“小”和“相等”的概念

stl中關聯容器內部的元素是排序的。STL 中的許多算法也涉及排序、查找。這些容器和算法都需要對元素進行比較。

默認情況下,比較大小是通過<運算符進行的,和>運算符無關。在STL中提到“大”、“小”的概念時,以下三個說法是等價的:

x 比 y 小。表達式x<y為真。y 比 x 大。


一定要注意,y比x大意味著x<y為真,而不是y>x為真。y>x的結果如何并不重要。
在 STL 中,x和y相等也往往不等價于x==y為真。對于在未排序的區間上進行的算法,如順序查找算法 find,查找過程中比較兩個元素是否相等用的是==運算符;但是對于在排好序的區間上進行查找、合并等操作的算法(如折半查找?binary_search,關聯容器自身函數 find)來說,x和y相等是與x<y和y<x同時為假等價的,與==運算符無關。

看上去x<y和y<x同時為假就應該和x==y為真等價,其實不然。例如下面的 class A:

class A{public:bool operator< (const A & a)const {return false;} };

可以看到,對任意兩個類 A 的對象 x、y,x<y和y<x都是為假的。也就是說,對 STL 的關聯容器和許多算法來說,任意兩個類 A 的對象都是相等的,這與==運算符的行為無關。

綜上所述,使用 STL 中的關聯容器和許多算法時,往往需要對<運算符進行適當的重載,使得這些容器和算法可以用<運算符對所操作的元素進行比較。最好將<運算符重載為全局函數,因為在重載為成員函數時,在有些編譯器上會出錯(由其 STL 源代碼的寫法導致)。

總結

以上是生活随笔為你收集整理的C++ STL与迭代器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。