effective STL 需要關注的條款和細節

1、拷貝對象是STL的方式(條款3)

容器操作處處有拷貝,比如 vector 的push_back(),但STL容器通常設計爲避免不必要的對象拷貝。一個使拷貝更高效、正確而且對分割問題免疫的簡單的方式是建立指針的容器而不是對象的容器。當然容器存指針需要額外的注意。

2、用empty()來代替檢查size()是否爲0(條款4)

對於所有的標準容器,empty()是一個常數時間的操作,但對於一些list實現,size()花費線性時間,有些實現需要遍歷整個list來得到size。

3、儘量使用區間成員函數代替循環包裹的單元素操作(條款5)

標準庫提供的區間成員函數執行效率往往比自己使用循環的效率高,而且代碼簡潔易維護,對於序列容器for循環的插入和刪除操作還需考慮迭代器的失效問題。

4、序列容器刪除多個元素時考慮remove+erase(條款9)

remove並不真正刪除元素,只是把不刪除的元素前移覆蓋掉需要刪除的元素。這樣不僅高效,而且不用考慮迭代器失效問題。list容器比較特殊用list::remove。

5、使用reserve來避免不必要的重新分配,使用swap節省內存(條款14、條款17)

vector的容量不足時會重新申請一塊更大的內存,每次以2爲因數增長,也就是說,當容器必須擴展時,它們的容量每次翻倍,然後把所有元素從容器的舊內存拷貝到它的新內存,再把舊的內存對象銷燬,內存釋放。如果需要一個較大的vector的時候,儘量用reserve來事先申請足夠大的內存,避免了vector的內存申請及拷貝等操作。

另外當vector刪除掉大部分對象後,可以通過交換技巧swap()構造新的小的vector來節省內存。

6、避免使用vector<bool>(條款18)

做爲一個STL容器,vector<bool>確實只有兩個問題。第一,它不是一個STL容器。第二,它並不容納bool。每個保存在“vector”中的“bool”佔用一個單獨的比特,而一個8比特的字節將容納8個“bool”。在內部,vector<bool>使用了與位域(bitfield)等價的思想來表示它假裝容納的bool。真的bool和化裝成bool的位域之間有一個重要的不同:你可以創建指向真的bool的指針,但卻禁止有指向單個比特的指針。引用單個比特也是禁止的。

7、相等與等價的不同(條款19)

std::find對“相同”的定義是 相等 ,基於operator==。set::insert對“相同”的定義是 等價 ,等價一般在每種標準關聯容器(比如,set、m ultiset、m ap和m ultim ap)的排序順序方面有意義通常基於operator< ,在一般情況下,用於關聯容器的比較函數不是operator<或甚至less,它是用戶定義的判斷式。等價並不意味着相等,比如實現一個不區分大小寫的set<string>,此時的比較函數會認爲“stl”和“Stl”是“相同”的,set<string>中只會存在一個“stl”,顯然“stl”和“Stl”並不相等。

8、爲指針的關聯容器指定比較類型(條款20)

容器會以指針的值排序,而不是以指針所指對象的值來排序。

9、比較函數對相等的值要返回false(條款21)

比較函數的返回值表明的是在此函數定義的排序方式下,一個值是否大於另一個。相等的值絕不該一個大於另一個,所以比較函數總應該對相等的值返回false。

10、避免原地修改set和m ultiset的鍵(條款22)

map和multi_map的鍵本身就是const的,肯定不可改變。同樣注意如果你改變set或multi_set裏的元素, 你必須確保不改變鍵的部分(如set裏面存的是員工類,排序函數對員工工號排序,員工工資則可以改變)。總之你可以改變和排序無關的部分。因爲關聯容器是有序的,強行修改將使得它們無序。

11、儘量用iterator代替const_iterator,reverse_iterator和const_reverse_iterator(條款26)

很多函數接口只支持iterator,iterator和const_iterator混用的時候會造成不必要的麻煩。

12 、用distance和advance把const_iterator轉化成iterator(條款27)

typedef deque<int> IntDeque; 
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator ConstIter;
IntDeque d;
ConstIter ci;
Iter i(d.begin()); // 初始化i爲d.begin()
advance(i, distance<ConstIter>(i, ci)); // 把i移到指向ci位置

13、儘量用成員函數代替同名的算法(條款44)

首先,成員函數更快。其次,比起算法來,它們與容器結合得更好(尤其是關聯容器)。那是因爲同名的算法和成員函數通常並不是是一樣的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章