C++容器使用經驗總結(一)

容器

1條:慎重選擇容器類型。

標準STL序列容器:vectorstringdequelist

標準STL關聯容器:setmultisetmapmultimap

非標準序列容器slistropeslist是一個單向鏈表,rope本質上是一“重型”string

非標準的關聯容器hash_sethase_multisethash_maphash_multimap

vector<char> 作爲string的替代。(見第13)

vector作爲標準關聯容器的替代。(見第23)

幾種標準的非STL容器,包括數組、bitsetvalarraystackqueuepriority_queue

你是否關心容器中的元素是如何排序的?如果不關心,選擇哈希容器.

容器中數據的佈局是否需要和C兼容?如果需要兼容,就只能選擇vector(見第16)

元素的查找速度是否是關鍵的考慮因素?如果是,就要考慮哈希容器、排序的vector和標準關聯容器-或許這就是優先順序。

對插入和刪除操作,你需要事務語義嗎?如果是,只能選擇list。因爲在標準容器中,只有list對多個元素的插入操作提供了事務語義。

deque是唯一的、迭代器可能會變爲無效(插入操作僅在容器末尾發生時,deque的迭代器可能會變爲無效)而指向數據的指針和引用依然有效的標準STL容器。

2條:不要試圖編寫獨立於容器類型的代碼。

如果你想編寫對大多數的容器都適用的代碼,你只能使用它們的功能的交集。不同的容器是不同的,它們有非常明顯的優缺點。它們並不是被設計用來交換使用的。

  你無法編寫獨立於容器的代碼,但是,它們(指客戶代碼)可能可以。

3條:確保容器中的對象拷貝正確而高效。

copy in,copy out,是STL的工作方式,它總的設計思想是爲了避免不必要的拷貝。使拷貝動作高效並且防止剝離問題發生的一個簡單辦法是使容器包含指針而不是對象。

4條:調用empty而不是檢查size()是否爲0

  理由很簡單:empty對所有的標準容器都是常數時間操作,而對一些list的實現,size耗費線性時間。

5條:區間成員函數優先於與之對應的單元素成員函數。

區間成員函數寫起來更容易,更能清楚地表達你的意圖,而且它們表現出了更高的效率。

6條:當心C++編譯器最煩人的分析機制。

把形參加括號是合法的,把整個形參的聲明(包括數據類型和形參名字)用括號括起來是非法的。

7條:如果容器中包含了通過new操作創建的指針,切記在容器對象析構前將指針delete掉。

STL很智能,但沒有智能到知道是否該刪除自己所包含的指針所指向的對象的程度。爲了避免資源泄漏,你必須在容器被析構前手工刪除其中的每個指針,或使用引用計數形式的智能指針(比如Boostsharedprt)代替指針。

8條:切勿創建包含auto_ptr的容器對象。

拷貝一個auto_ptr意味着改變它的值。例如對一個包含auto_ptrvector調用sort排序,結果是vector的幾個元素被置爲NULL而相應的元素被刪除了。

9條:慎重選擇刪除元素的方法。

要刪除容器中指定值的所有對象:

如果容器是vectorstringdeque,則使用erase-remove習慣用法。

SeqContainer<int> c;

c.erase(remove(c.begin(),c.end(),1963),c.end());

如果容器是list,則使用list::remove

如果容器是一個標準關聯容器,則使用它的erase成員函數。

要刪除容器中滿足特定條件的所有對象:

如果容器是vectorstringdeque,則使用erase-remove_if習慣用法。

如果容器是list,則使用list::remove_if

如果容器是一個標準關聯容器,則使用remove_copy_ifswap,或者寫一個循環遍歷容器的元素,記住當把迭代器傳給erase時,要對它進行後綴遞增。

AssocCOntainer<int> c;

...

AssocContainer<int> goodValues;

remove_copy_if(c.begin(), c.end(), inserter(goodValues, goodValues.end()),badValue);

c.swap(goodValues);

for(AssocContainer<int>::iterator i = c.begin();i !=c.end();/* do nothing */){

if(badValue(*i)) c.erase(i++);

else ++i;

}

要在循環內部做某些(除了刪除對象之外的)操作:

如果容器是一個標準序列容器,則寫一個循環來遍歷容器中的元素,記住每次掉用erase時,要用它的返回值更新迭代器。

如果容器是一個標準關聯容器,則寫一個循環來遍歷容器中的元素,記住每次把迭代器傳給erase時,要對迭代器做後綴遞增。

10條:瞭解分配子(allocator)的約定和限制。

11條:理解自定義分配子的合理用法。

12條:切勿對STL容器的線程安全性有不切實際的依賴。

對一個STL實現你最多隻能期望:

多個線程讀是安全的。

多個線程對不同的容器寫入操作是安全的。

你不能期望STL庫會把你從手工同步控制中解脫出來,而且你不能依賴於任何線程支持。


發佈了20 篇原創文章 · 獲贊 5 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章