C primer 四 標準庫型別vector

2021-07-25 05:07:25 字數 4936 閱讀 3734

標準庫型別vector表示物件的集合,其中所有物件的型別都相同。集合中的每個物件都有乙個與之對應的索引,索引用於訪問物件。因為vector 「容納著」其他物件,所 以它也常被稱作容器(container)。

要想使用vector,必須包含適當的標頭檔案。在後續的例+中,都將假定做了如下 using宣告:

#include

using std::vector;

定義和初始化vector物件

和任何一種類型別一樣,vector模板控制著定義和初始化向量的方法。表3.4列出 了定義vector物件的常用方法。

當然也可以在定義vector物件時指定元素的初始值。例如,允許把乙個vector對 象的元素拷貝給另外乙個vector物件。此時,新vector物件的元素就是原vector 物件對應元素的副本。注意兩個vector物件的型別必須相同:

vectorivec;       //相始狀態為空

//在此處給ivec新增一些值

vectorivec2(ivec); //

把ivec的元素拷貝給ivec2

vectorivec3 = ivec; //

把ivec的元素拷貝給ivec3

vectorsvec(ivec2); //

錯誤:svec的元素是string物件,不是int

列表初始化vector物件

c++11新標準還提供了另外一種為vector物件的元素賦初值的方法,即列表初始化。此時,用花括號括起來的0個或多個初始元素值被賦給vector物件: 

vectorarticles = ;

向vector物件屮新增元素

對vector物件來說,直接初始化的方式迠用於三種情況:初始值已知且數量較少、 初始值是另乙個vector物件的副本、所有元素的初始值都一樣。然而更常見的情況是: 建立乙個vector物件時並不清楚實際所需的元素個數,元素的值也經常無法確定。還有些時候即使元素的初值已知,但如果這些值總量較大而各不相同,那麼在建立vector對 象的時候執行初始化操作也會顯得過於煩瑣。

更好的處理方法是先建立乙個空vector,然後在執行時再利用vector的成員函式 push_back向其中新增元素。push_back負責把乙個值當成vector物件的尾元素「壓到(push)」 vector物件的「尾端(back)」。例如:

vectorv2; // 空 vector 物件

for (int i = 0; i != 100; ++i)

v2 .push_back(i);//依次把整數值放到v2尾端 //迴圈結束後v2有100個元素,值從0到99
在上例中,儘管知道vector物件最後會包含100個元素,但在一開始還是把它宣告成空 vector,在每次迭代時才順序地把乙個整數作為v2的新元素新增給它。

其他vector操作

除了 push_back之外,vector還提供了兒種其他操作,大多數都和string的相 關操作類似,£3.5列出了其中比較重要的一些。

訪m vector物件中兀素的方法和訪問string物件中字元的方法差不多,也是通過 元素在vector物件中的位置。例如,可以使用範圍for語句處理vector物件中的所有元素:

vectorv;

for (auto &i : v) //對於v中的每個元素(注意:i是乙個引用)

i *= i; //求元素值的平方

for (auto i : v) //對於v中的每個元素

cout « i « ""; //輸出該元素

cout << endl;

注意:在這裡for()屬於基於範圍的for語句。

第乙個迴圈把控制變數i定義成引用型別,這樣就能通過i給v的元素賦值,其中i的 型別由auto關鍵字指定。這裡用到了一種新的復合賦值運算子。 如我們所知,+=把左側運算物件和右側運算物件相加,結果存入左側運算物件;類似的, *=把左側運算物件和右側運算物件相乘,結果存入左側運算物件。最後,第二個迴圈輸出所有元素。

計算vector內物件的索引

使用下標運算子能獲取到指定的元素。和string一樣, vector物件的下標也是從0開始計起,下標的型別是相應的size_type型別。只要 vector物件不是乙個常量,就能向下標運算子返回的元素賦值。此時,也能通過計算得到vector內物件的索引,然後直接獲取索引位置 上的元素。

//使用下標

for(decltype(vstr.size()) in=0;in!=vstr.size();in++)

cout

迭代器介紹

我們已經知道可以使用下標運算子來汸問string物件的字元或vector物件的元素,還有另外一種更通用的機制也可以實現同樣的目的,這就是迭代器(iterator)。除了vector之外,標準庫還定義了其他幾種容器。所有標準庫容器 都可以使用迭代器,但是其中只有少數幾種才同時支援下標運算子。嚴格來說,string 物件不屬於容器型別,但是string支援很多與容器型別類似的操作。vector支援下標運算子,這點和string一樣;string支援迭代器,這也和vector是一樣的。

類似於指標型別,迭代器也提供了對物件的間接訪問。就迭代器而自,其物件是容器中的元素或者string物件中的字元。使用迭代器可以訪問某個元素,迭代器也能從乙個元素移動到另外乙個元素。迭代器有有效和無效之分,這一點和指標差不多。有效的迭代器或者指向某個元素,或者指向容器中尾元素的下一位置:其他所有情況都屬於無效。

使用迭代器

和指標不一樣的是,獲取迭代器不是使用取位址符,有迭代器的型別問時擁有返回迭 代器的成員。比如,這些型別都擁有名為begin和end的成員,其中begin成員負責返回指向第乙個元素(或第乙個字元)的迭代器。如有下述語句:

//由編譯器決定b和e的型別

// b表示v的第乙個元素,e表示v尾元素的下一位置

auto b = v.begin(), e = v.end(>; //b 和 e 的型別相同

end成員則負責返回指向容器(或string物件)「尾元素的下一位置(one past the end)」 的迭代器,也就是說,該迭代器指示的是容器的乙個本不存在的「尾後(off the end)」元素。這樣的迭代器沒什麼實際含義,僅是個標記而己,表示我們己經處理完了容器中的所 有元素。end成員返問的迭代器常被稱作尾後迭代器(off-the-end iterator)或者簡稱為尾 迭代器(end iterator)。特殊情況下如果容器為空,貝lj begin和end返回的是同乙個迭 代器。

如果容器為空,則begin和end返回的是同乙個迭代器,都是尾後迭代器。

迭代器運算子

表列舉了迭代器支援的一些運算。使用==和!=來比較兩個合法的迭代器是否相等,如果兩個迭代器指向的元素相同或者都是同乙個容器的尾後迭代器,則它們相等;否則就說這兩個迭代器不相等。

和指標類似,也能通過解引用迭代器來獲取它所指示的元素,執行解引用的迭代器必須合法並確實指示著某個元素。試**引用乙個非法迭代器或 者尾後迭代器都是未被定義的行為。

舉個例子,利用下標運算子把string物件的第乙個字 付改為了大寫形式,下面利用迭代器實現同樣的功能:

string s("some string");

if (s .begin ()!= s • end ()) 

程式例子:

#include

#include

using std::cin;

using std::cout;

using std::vector;

using std::string;

int main(void)

cout< }

cout<

//使用下標

for(decltype(vstr.size()) in=0;in!=vstr.size();in++)

cout< }

cout<

//使用迭代器

for(auto it=vstr.begin();it!=vstr.end();it++)

cout<

cout<

return 0; }

輸出結果:

c primer 3 標準庫型別

3.1 命名空間的using宣告 using宣告是對某個命名空間做引入。主要作用是簡化 編寫。比如用cout的三種方式 using namespace std using std cout std cout 3.2 標準庫string型別 定義和初始化 include using std strin...

C Primer 學習筆記(二) 標準庫型別

一 命名空間的using指示與using宣告 1 using宣告 1 乙個using宣告一次只引入乙個命名空間成員。2 using宣告的作用域為 從using宣告點開始,直到包含該using宣告的作用域的末尾,名字都是可見的。類作用域中的using宣告侷限於被定義類的基類中定義的名字。using s...

c primer學習筆記2 標準庫型別

1 string.size 的返回值型別為string size type,而不是int,不要把size的返回值賦給乙個int變數,可能溢位 實際上很多庫型別size操作的返回值型別都是size type型別,這是一種類似unsigned int的型別 同樣在進行索引時索引值也是size type型...