這部分的內容你在寫程式的時候肯定是處處都能用到的,而且會讓你的程式很簡潔。本章其實是第三章內容的拓展,詳細地介紹了標準庫順序容器的知識。
乙個容器就是一些
特定同一型別
物件的集合。順序容器為程式設計師提供了控制元素儲存和訪問順序的能力。這種順序不依賴於元素的值,而是與元素加入容器時的位置相對應。
所有順序容器都提供了快速順序訪問元素的能力,但不同容器在兩個方面的效能不同
:向容器中新增或刪除元素
非順序(隨機)訪問容器中的元素
除非你有很好的理由選擇其他容器,否則一律用vector你可以看到每乙個容器都對效能有所側重,都是有不同的靈活度,那我們在選擇容器的時候應該選哪種呢?
這部分介紹對所有容器都適用的操作
一般來說,每個容器都定義在乙個標頭檔案中,檔名和型別名相同,例如,deque定義在標頭檔案deque中。
容器均定義為模板類,對於大多數,我們必須提供額外資訊來生成特定的容器型別:
lista;
vectorb;
對容器可以儲存的元素型別的限制
順序容器幾乎可以儲存任意型別的元素,包括它自己。也有一些例外,比如說,我要儲存乙個類型別的物件,而這個類沒有預設建構函式,於是,我得自己給它提供乙個元素初始化器:
//假定a是乙個沒有預設建構函式的型別
vectorv1(10, init); //正確:init是乙個a物件,相當於提供了初值,v1中有10個init
vectorv2(10); //錯誤:無法初始化
所有容器都支援的操作我直接貼了,反正也記不住,多用用才知道。
在我的之前一篇部落格中有介紹:
迭代器寫乙個程式看看吧,輸出容器中所有元素:
vectora(10, 1);
auto beg = a.begin();
while(beg != a.end())
迭代器可加可減,但forward_list不支援減,理由顯而易見。
容器型別成員
每個容器都定義了多個型別,如前面中的第一部分型別別名,我們其實已經用過三種:size_type、iterator和const_iterator。 大多數容器還提供反向迭代器,反向迭代器++就是上乙個元素。
通過型別別名,我們可以在不了解容器中元素型別的情況下使用它:
list::iterator iter; //iter是通過list定義的乙個迭代器型別
vector::difference_type count;
//count是通過vector定義的乙個difference_type型別
begin和end成員lista = ;
auto it1 = a.begin(); //list::iterator
auto it2 = a.rbegin(); //list::reverse_iterator
auto it3 = a.cbegin(); //list::const_iterator
auto it4 = a.crbegin(); //list::const_reverse_iterator
當不需要修改時,最好用cbegin
容器定義和初始化
每個容器型別都定義了乙個預設建構函式。除了array之外,其他容器的預設建構函式都會建立乙個指定型別的空容器,且都可以接受指定容器大小和元素初始值的引數。
下圖已經說得很清楚了,不清楚的就繼續看我下面的囉嗦吧
將乙個容器初始化為另乙個容器的拷貝
兩種方式:
直接拷貝整個容器
拷貝由乙個迭代器對指定的元素範圍(array除外) 二者在元素型別的要求嚴格程度上有所不同,第一種容器型別和容器內元素型別必須完全匹配,第二種容器型別無所謂,因為被迭代器隱藏了嘛,容器內元素型別能轉換就行。看**:
lista = ; //列表初始化
vectorb = ;
lista1(a); //正確
dequea2(a); //錯誤:容器型別不匹配
vectorb1(b); //錯誤:容器內元素型別不匹配
forward_listb2(b.begin(), b.end()); //正確
與順序容器大小相關的建構函式
這個麼,也還是好用的:
vectora1(10, -1); //10個-1
vectora2(10); //10個0
vectora3(10); //10個空string
如果元素型別是內建型別或者有預設建構函式的類型別,可以在初始化的時候只為建構函式提供乙個容器大小引數;如果沒有預設建構函式,必須要顯式地提供初值。
標準庫array具有固定大小
與內建陣列一樣,array的大小也是型別的一部分:
array; //型別是3個int的陣列
arraya1; //10個0
arraya2 = ; //列表初始化
arraya3 = ; //5, 0, 0
我們不能對內建陣列進行拷貝或物件賦值,但array可以(可能這也是為什麼搞出array的原因):
arraya = ;
arraycopy = a;
賦值和swapvectora1 = ;
vectora2 =a1;
a2 = ; //這樣都行哦,大小變為2
arrayb1 = ;
b1 = ; //這樣不行
關於array,書上是這樣說的:由於右邊物件大小可能和左邊物件大小不同,所以array索性不支援用花括號賦值和assgin。(我自己試了下,小於等於原來的元素數量是可以的)
使用assign(僅順序容器)
賦值運算子要求兩邊運算物件型別相同,使用assign可以從乙個不同但是相容的型別來賦值:
listname;
vectorold;
names = old; //錯誤,容器型別不匹配
names.assign(old.cbegin(), old.cend()); //正確,char*能轉換為string
names.assign(10, "h"); //assign過載版本,10個h
使用swapvectors1(10);
vectors2(20);
swap(s1, s2); //交換後,s1有20個元素,s2有10個元素
除了array之外(它是真正交換元素了),交換兩個容器的操作很快,是常數時間,因為swap只是交換了兩個容器的內部資料結構,並沒有真正移動元素,所以啊,原來那些指標、引用都還是指向原來的。array就會指向交換後的了,畢竟人家來真的。
與其他容器不同,對乙個string呼叫swap會讓指標、引用、迭代器等失效。
容器大小操作
名稱含義
size
返回容器中元素個數
empty
只在size為0時返回true
max_size
返回乙個大於或等於該容器所能容納的最大元素個數
關係運算子
容器裝的元素型別支援關係運算,我們才能來用它,先來看內建型別的,它們肯定被實現得很好,畢竟c++高手
vectorv1 = ;
vectorv2 = ;
vectorv3 = ;
vectorv4 = ;
v1 < v2;
v1 > v3;
v1 == v4;
關係運算中判等用==,大小用
vectora, b;
if(a < b) //錯誤,沒定義《運算子
C Primer 第9章筆記
9.1 順序容器概述 順序容器型別 forward list沒有size操作。9.2 容器庫概覽 一般來說,每個容器都定義在乙個與型別名相同的標頭檔案中,容器均定義為模板類。對容器可以儲存的元素型別的限制 如沒有預設建構函式的物件。容器操作 型別別名 建構函式 賦值與swap 大小 新增 刪除元素 ...
c primer 學習筆記 1 第1 5章
1.輸入輸出 流 隨著時間的推移,字元是順序生成或消耗的 std cout hello world endl 運算子接受兩個運算物件,左側必須是ostream,右側是要列印的值,計算結果返回ostream物件中。上述使用兩次 運算子,第一次運算結果成了第二次的左側物件。note 在寫過載 運算子是要...
《c primer》筆記 第1章 開始
main的返回值被用來指示狀態。返回值0表明成功,非0的返回值的含義由系統定義,通常用來指出錯誤型別.寫乙個簡單的測試程式 include int main g g oprogl progl cc o progl是編譯器引數,指定了可執行檔案的檔名。cl從vs2013 開發人員命令提示啟動 cl e...