C primer 讀書筆記 第九章 順序容器

2021-07-11 11:12:21 字數 4954 閱讀 6066

1、順序容器:

vector:支援快速隨機訪問

deque:雙端佇列

list:支援快速插入/刪除

2、順序容器介面卡:

stack:後進先出(lifo)棧

queue:先進先出(fifo)佇列

priority_queue:有優先順序佇列管理的佇列

3、所有的容器都是類模板。定義乙個容器型別的物件之前必須包含相關標頭檔案

#include

#include

#include

4、容器元素型別的兩個約束條件:

1)元素型別必須支援賦值運算;

2) 元素型別的物件必須可以複製。

除輸入輸出(io)標準庫型別之外,所有其他標準庫型別都是有效的容器元素型別。特殊地,容器本身也滿足上述要求。io庫型別不支援複製或賦值,所以不能建立存放io型別物件的容器。

在容器本身作為容器的元素時,必須使用如下空格:

vector> ivec;

必須用空格隔開兩個相鄰的 > 符號,以示這是兩個分開的符號,否則,系統會認為 >> 是單個符號,為右移操作符,並導致編譯錯誤。

5、迭代器範圍是乙個左閉合區間,其標準表示方式為:[ first, last)。

first 和last迭代器必須滿足下面兩個條件:

1) 它們指向同乙個容器的元素或者超出末端的下乙個位置。

2) last絕對不能位於first之前。

6、使迭代器失效的容器操作

一些容器操作會修改容器內在狀態或移動容器內的元素,這樣的操作會使所有指向元素的迭代器失效,同時也使其它迭代器失效。使用失效的迭代器是沒有定義的,可能會導致與懸垂指標相同的問題。

1) 容器的erase函式

c.erase(p)     刪除迭代器p所指向的元素

返回乙個迭代器,它指向被刪除元素後面的元素。如果p指向容器中得最後乙個元素,則返回的迭代器指向容器的超出末端的下乙個位置。如果p就是指向超出容器末端的下乙個位置的迭代器,則該操作未定義。

for (vector::iterator iter = ivec.begin(); iter != ivec.end();++iter) 

}

erase刪除元素後返回指向下乙個元素的迭代器,而for迴圈中迭代器自增,所以if語句中要將迭代器減去1,以免漏處理元素。

2)任何insert 或 push 操作(新增元素操作)都可能導致迭代器失效。當編寫迴圈將元素插入到vector或者deque容器中時,程式必須確保迭代器在每次迴圈後都得到更新。

c.insert(p,t)     在迭代器p所指向的元素前面插入值為t的新元素。返回指向新新增的元素的迭代器

while(first != v.end())

3)不要儲存end操作返回的迭代器。可以在每次做完插入運算後重新計算end迭代器值。

for(vector::iterator iter = ivec.begin();iter != ivec.end(); ++iter)

7、容器元素都是副本

在容器中新增元素時,系統是將元素值複製到容器裡。容器裡的元素與原來的元素互不相干。

8、vector容器的自增長

為了支援快速的隨機訪問,vector容器的元素以連續的方式存放。因為元素是連續存放的,如果在新增乙個元素的時候,容器已經沒有足夠的空間容納新的元素,vector為保證連續存放元素,必須重新分配儲存空間,用於存放原來的元素和新新增的元素,最後撤銷就得空間。如果vector容器在每次新增新元素時,都要這麼分配和撤銷記憶體空間,其效能將會非常緩慢。

對於不連續儲存元素的容器,不存在這樣的記憶體分配問題。在list容器新增乙個新元素非常方便。

由此可以推論,一般而言,使用list容器優於vector容器。但事實上,對於大部分應用,使用vector容器是最好的。原因在於,標準庫的實現者使用這樣的記憶體分配策略:以最小的代價連續儲存元素。由此而帶來的訪問元素的遍歷彌補了其儲存代價。

為了使vector容器實現快速的記憶體分配策略,其實際分配的容量要比當前所需的空間多一些。vector預留了額外的儲存區,用於存放新新增的元素。

win7 + eclipse + 32位系統下測試:

vectorivec;

cout << "size:"<::size_type ix = 0; ix !=24;++ix) {

ivec.push_back(ix);

cout << "size:"<

size:0 capacity:0

size:1 capacity:1

size:2 capacity:2

size:3 capacity:4

size:4 capacity:4

size:5 capacity:8

size:6 capacity:8

size:7 capacity:8

size:8 capacity:8

size:9 capacity:16

size:10 capacity:16

size:11 capacity:16

size:12 capacity:16

size:13 capacity:16

size:14 capacity:16

size:15 capacity:16

size:16 capacity:16

size:17 capacity:32

size:18 capacity:32

size:19 capacity:32

size:20 capacity:32

size:21 capacity:32

size:22 capacity:32

size:23 capacity:32

size:24 capacity:32

可以看出這個編譯器中的分配策略是:當記憶體空間不夠的時候加倍記憶體空間。

capacity:0 -> 2^0 -> 2^1 -> 2^2 -> 2^3 -> 2^4 -> 2^5 ->......

9、容器的選用

vector和的確容器提供了對元素的快速隨機訪問,但代價是,在容器的任意位置插入或刪除元素,比在容器尾部插入和刪除的開銷更大。list型別在任何位置都能快速插入和刪除,但付出的代價是元素的隨機訪問開銷更較大。

1)插入操作影響容器的選擇:

list容器表示不連續的記憶體區域,在任何位置都能搞笑地inser或erase乙個元素。插入或刪除乙個元素不需要移動其他任何元素。

對於vector容器,除了尾部外,在任何其他位置的插入和刪除操作都要求移動被插入或者刪除元素右邊的所有元素。

deque容器擁有更複雜的資料結構。在deque容器的中間insert或erase元素效率較低,但是在deque首部和尾部能快速實現insert和erase操作。

2)元素的隨機訪問影響容器的選擇:

vector和deque容器都支援對元素實現高效的隨機訪問。在list容器中要實現隨機訪問只能是順序跟隨指標,效率很低。

3)選擇容器型別的法則:

(1)如果程式要求隨機訪問元素,則應使用vector或者deque容器。

(2)如果程式必須在容器的中間位置插入或者刪除元素,則應選擇list容器。

(3)如果程式不是在容器的中間位置,而是在容器的首部或者尾部插入或者刪除元素,則應該採用deque容器。

(4)如果只需要在讀取輸入時在容器的中間位置插入元素,然後需要隨機訪問元素,則可以考慮在輸入時將元素讀入到乙個list容器中,接著對此容器重新排序,使其適合順序訪問,然後將排序的list容器複製到乙個vector容器中。

(5)如果程式既要隨機訪問又必須在容器中間位置插入或刪除元素,此時選擇容器取決於下面兩種操作付出的代價:隨機訪問list容器元素的代價,在vector或deque容器中插入或刪除元素時複製元素的代價。容器的選擇主要取決於程式中使用更多的是訪問操作還是插入或刪除操作。

(6)如果無法確定改採用哪種容器,則編寫**時嘗試只使用vector和list容器都提供的操作,使用迭代器,而不是下標,並且避免隨機訪問元素。這樣在必要時,可以很方便的將程式從使用vector容器修改為list容器。

注:通常來說,除非找到選擇使用其他容器的更好的理由,否則vector容器都是最佳選擇。

10、string型別

1)string型別的查詢操作

s.find(args)                         在s中查詢args字串的第一次出現

s.rfind(args)                        在s中查詢args字串的最後一次出現

s.find_first_of(args)            在s中查詢args中任意字元的第一次出現

s.find_last_of(args)            在s中查詢args中任意字元的最後一次出現

s.find_first_not_of(args)     在s中查詢第乙個不屬於args的字元

s.find_last_not_of(args)      在s中查詢最後乙個不屬於args的字元

eg:查詢字串中第乙個出現的數字

string number = "0123456789";

string str = "r2d2";

string::size_type pos = str.find_first_of(number);

cout << "found number at index: " << pos <<

"element is: " << str[pos] << endl;

2)string物件的比較函式

s.compare(s2)        比較s和s2,返回值可能是正數(s > s2)、0(s == s2)、負數(s < s2)。

11、容器介面卡

這塊還不是很理解其作用是什麼。

第九章 讀書筆記

這一章主要講的是硬體抽象層 hal hal hardware abstraction layer,硬體抽象層 是建立在 linux 驅動之上的一套程式庫。這套程式庫並不屬於 linux 核心,而是屬於 linux 核心層之上的應用層。google為 android 加入hal 主要目的如下 1 統一...

C primer 第九章筆記 初稿

性質 容器中元素的順序與加入的位置相對應,為使用者提供了控制元素儲存和訪問順序的能力。六大順序容器 名稱功能 特點 vector 可變大小陣列 支援快速隨機訪問,除尾部外插入 刪除較慢 deque 雙端佇列 支援快速隨機訪問,頭尾外插入刪除較慢 list 雙向列表 支援雙向順序訪問,任何位置插入刪除...

C primer 第九章個人筆記

個人筆記,txt備份用。不考慮排版。順序容器型別 vector 可變陣列,支援快速隨機訪問 在尾部之外的地方插入元素不方便 deque 雙端佇列,支援快速隨機訪問,在首尾部之外的地方插入刪除元素麻煩 list 雙向鍊錶 任何位置插入刪除元素快 只能雙向訪問 forward list 單向鍊錶 任何位...