C primer 學習筆記 第9章(1)

2021-07-25 13:19:38 字數 4038 閱讀 6963

這部分的內容你在寫程式的時候肯定是處處都能用到的,而且會讓你的程式很簡潔。本章其實是第三章內容的拓展,詳細地介紹了標準庫順序容器的知識。

乙個容器就是一些

特定同一型別

物件的集合。順序容器為程式設計師提供了控制元素儲存和訪問順序的能力。這種順序不依賴於元素的值,而是與元素加入容器時的位置相對應。

所有順序容器都提供了快速順序訪問元素的能力,但不同容器在兩個方面的效能不同

:向容器中新增或刪除元素

非順序(隨機)訪問容器中的元素

除非你有很好的理由選擇其他容器,否則一律用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;

賦值和swap
vectora1 = ;

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

使用swap
vectors1(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...