【C++】Effective STL:50条有效使用STL的经验
第一條:慎重選擇容器類型
1、C++容器:先混個(gè)眼熟
序列容器:array、vector、string、deque、list、forward_list
有序關(guān)聯(lián)容器:set、map、multiset、multimap
無(wú)序關(guān)聯(lián)容器:unordered_set、unordered_map、unordered_multiset、unordered_multimap
容器適配器:stack、queue、priority_queue
2、C++容器:簡(jiǎn)介
2.1 序列容器
序列容器實(shí)現(xiàn)了可以順序訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。
array:靜態(tài)連續(xù)容器;
vector:動(dòng)態(tài)連續(xù)容器,超出容器大小會(huì)自動(dòng)分配內(nèi)存;
deque:雙端隊(duì)列;
list:雙鏈表;
forward_list:單鏈表;
2.2 有序關(guān)聯(lián)容器
關(guān)聯(lián)容器實(shí)現(xiàn)可以快速搜索的排序數(shù)據(jù)結(jié)構(gòu)(O(log n)復(fù)雜度)。
set:只有鍵,沒(méi)有值的集合,按鍵排序,并且鍵是唯一的;
map:鍵值對(duì)的集合,按鍵排序,并且鍵是唯一的;
multiset:只有鍵,沒(méi)有值的集合,按鍵排序,鍵可以不唯一;
multimap:鍵值對(duì)的集合,按鍵排序,鍵可以不唯一;
2.3 無(wú)序關(guān)聯(lián)容器
無(wú)序關(guān)聯(lián)容器實(shí)現(xiàn)了可以快速搜索的未排序(哈希)數(shù)據(jù)結(jié)構(gòu)(O(1)最好,O(n)最壞情況的復(fù)雜性)。
unordered_set:只有鍵,沒(méi)有值的集合,按鍵哈希散列,并且鍵是唯一的;
unordered_map:鍵值對(duì)的集合,按鍵哈希散列,并且鍵是唯一的;
unordered_multiset:只有鍵,沒(méi)有值的集合,按鍵哈希散列,鍵可以不唯一;
unordered_multimap:鍵值對(duì)的集合,按鍵哈希散列,鍵可以不唯一;
2.4容器適配器
容器適配器為順序容器提供了不同的接口。
stack:先進(jìn)后出;
queue:先進(jìn)先出;
priority_queue:優(yōu)先級(jí)隊(duì)列
3、選擇容器
默認(rèn)序列容器:vector,先考慮vector是否符合要求,如果不符合再選擇其它的;
容器大小從始至終不會(huì)變,選擇array:例如記錄一年中每個(gè)月的收入;
需要在序列中間做插入和刪除操作,選擇list;
需要在序列頭部、尾部做插入和刪除操作時(shí),選擇deque;
第二條:不要試圖編寫(xiě)?yīng)毩⒂谌萜黝愋偷拇a
1、禁止對(duì)容器進(jìn)一步泛化
每一種容器是針對(duì)一類場(chǎng)景的泛化,不要試圖進(jìn)一步泛化容器。比如:針對(duì)當(dāng)下場(chǎng)景使用vector容器,寫(xiě)代碼時(shí)就圍繞vector接口來(lái)寫(xiě),不要試圖寫(xiě)出能夠兼容list、deque的代碼。雖然這么做出發(fā)點(diǎn)是好的,但是最終總是誤入歧途。
2、建議封裝容器到類中
要想減少再替換容器類型時(shí)所需要修改的代碼,可以把容器隱藏到一個(gè)類中,并盡量減少與容器相關(guān)的外部可見(jiàn)的接口。
第三條:確保容器中的對(duì)象拷貝正確而高效
1、使用智能指針
使拷貝動(dòng)作高效、正確,并防止剝離問(wèn)題發(fā)生的一個(gè)簡(jiǎn)單辦法是使容器包含指針而不是對(duì)象,最佳選擇是使用智能指針。
第四條:調(diào)用empty而不是檢查size()是否為0
理由很的簡(jiǎn)單:empty對(duì)所有的標(biāo)準(zhǔn)容器都是常數(shù)時(shí)間操作,而對(duì)一些list實(shí)現(xiàn),size耗時(shí)線性增長(zhǎng)。
第五條:區(qū)間成員函數(shù)優(yōu)于與之對(duì)應(yīng)的單元素成員函數(shù)
1、區(qū)間成員函數(shù)
區(qū)間成員函數(shù)像STL算法一樣,使用兩個(gè)迭代器參數(shù)來(lái)確定該成員操作所執(zhí)行的區(qū)間。
2、區(qū)間成員函數(shù)的優(yōu)點(diǎn)
代碼量少、表達(dá)清晰直接,易寫(xiě)易懂。
3、何時(shí)使用區(qū)間成員函數(shù)
1)通過(guò)利用插入迭代器的方式來(lái)限定目標(biāo)區(qū)間的copy調(diào)用,幾乎都應(yīng)該被替換為對(duì)區(qū)間成員函數(shù)的調(diào)用;
2)所有標(biāo)準(zhǔn)容器都提供了使用區(qū)間創(chuàng)建的構(gòu)造函數(shù);
3)所有標(biāo)準(zhǔn)容器都提供了使用區(qū)間插入的insert函數(shù);
4)所有標(biāo)準(zhǔn)容器都提供了使用區(qū)間刪除的erase函數(shù);
5)所有標(biāo)準(zhǔn)容器都提供了使用區(qū)間賦值的assign函數(shù)
第六條:當(dāng)心C++編譯器最煩人的分析機(jī)制
請(qǐng)使用命名的迭代器對(duì)象,這消除二義性,維護(hù)代碼的人更容易理解。
這里舉例一個(gè)容易犯錯(cuò)的代碼:將變量定義寫(xiě)成了函數(shù)聲明。
第七條:如果容器中包含了通過(guò)new操作創(chuàng)建的指針,切記在容器對(duì)象析構(gòu)前將指針delete掉
STL容器很智能,但沒(méi)有智能到知道是否該刪除自己所包含的指針?biāo)赶虻目臻g。為了避免內(nèi)存泄漏,建議使用引用計(jì)數(shù)形式的智能指針對(duì)象。
第八條:切勿創(chuàng)建包含auto_ptr的容器對(duì)象
不多說(shuō)了,很多年以前就不再使用auto_ptr了。
第九條:慎重選擇刪除元素的方法
1、刪除特定值
對(duì)于連續(xù)容器,使用erase-remove:v.erase(remove(v.begin(), v.end(), 1987), c.end());
對(duì)于非連續(xù)容器list,使用remove函數(shù);
對(duì)于關(guān)聯(lián)容器,使用erase;
2、刪除滿足特定條件的對(duì)象
對(duì)于連續(xù)容器,使用erase-remove_if;
對(duì)于非連續(xù)容器,使用list::remove_if
對(duì)于關(guān)聯(lián)容器,使用remove_copy_if和swap或者遍歷使用erase,注意參數(shù)使用后綴遞增;
第十條:了解分配子(allocator)的約定和限制
一個(gè)類型為T(mén)的對(duì)象,它的默認(rèn)分配子allocator的兩個(gè)類型定義分別是allocator::pointer和allocator::reference。
其他待完善,沒(méi)有理解分配子的作用。
第十一條:理解自定義分配子的合理用法
第十二條:切勿對(duì)STL容器的線程安全性有不切實(shí)際的依賴
對(duì)容器成員函數(shù)的每次調(diào)用,都鎖住容器直到調(diào)用結(jié)束;
在容器返回的每個(gè)迭代器的生存期結(jié)束前,都鎖住容器;
第十三條:vector和string優(yōu)先于動(dòng)態(tài)分配的數(shù)組
不解釋了,直接照做就是了。
第十四條:使用reserver來(lái)避免不必要的重新分配
reserver成員函數(shù)能使你把重新分配的次數(shù)減少到最低限度。
size:容器中有多少元素;注意:不等于容器容納多少元素;
capacity:容器已經(jīng)分配的內(nèi)存可以容納多少元素;
resize:強(qiáng)迫容器改變到包含n個(gè)元素的狀態(tài)。
reserve:強(qiáng)迫容器把它的容器變?yōu)橹辽偈莕,如果n不小于當(dāng)前的大小,會(huì)重新分配;如果小于,什么也不做。
第十五條:注意string實(shí)現(xiàn)的多樣性
不同的string實(shí)現(xiàn)以不同的方式來(lái)組織下列信息:字符串的大小、容量capacity、字符串的值、對(duì)值的引用計(jì)數(shù)。
第十六條:了解如果把vector和string數(shù)據(jù)傳給舊的API
vector返回C API:
vector<int> v;
if(!v.empty()){doSomething(&v[0], v.size());
}
注意:不要用v.begin()代替&v[0]
string返回C API:s.c_str();
第十七條:使用“swap技巧”除去多余的容量
class Contestant{... ...};
vector<Contestant> contestants;
... ...
vector<Contestant>(contestants).swap(contestants);
string s;
... ...
string(s).swap(s);
第十八條:避免使用vector
首先,它不是一個(gè)STL容器;
其次,它并不存儲(chǔ)bool
代替方法:
deque<bool>
或者使用bitset
第十九條:理解相等(equality)和等價(jià)(equivalence)的區(qū)別
相等:operator==
等價(jià):!(x<y) && !(y<x),對(duì)于兩個(gè)對(duì)象x和y,如果按照關(guān)聯(lián)容器c的排列順序,每個(gè)都不在另一個(gè)的前面,那么稱這兩個(gè)對(duì)象按照c的排列順序是等價(jià)的。
第二十條:為包含指針的關(guān)聯(lián)容器指定比較類型
如果什么也不做,默認(rèn)是對(duì)指針的地址做排序。必須自己編寫(xiě)比較函數(shù)子類。
比較函數(shù)模板如下:
struct DereferenceLess {tumplate<typename PtrType>bool operator()(PtrType pT1, PtyType pT2) const{return *pT1 < *pT2;}
}
第二十一條:總是讓比較函數(shù)在等值情況下返回false
如果比較函數(shù)在等值情況下返回true,兩個(gè)相等的值,可能不等價(jià)。
比如使用less_equal(operator<=)作為比較函數(shù),x=y=10時(shí),!(x<=y) && !(y<=x)的結(jié)果為false,即最終會(huì)得出:x!=y
第二十二條:切勿直接修改set或multiset的值
所有的標(biāo)準(zhǔn)關(guān)聯(lián)容器是按照一定順序來(lái)存放的,如果修改了會(huì)打破容器的有序性。
第二十三條:考慮用排序的vector替代關(guān)聯(lián)容器
如果元素少并且?guī)缀醪粫?huì)有插入刪除操作,可以考慮使用排序的vector替代關(guān)聯(lián)容器,無(wú)論是空間還是時(shí)間都是最優(yōu)的。
第二十四條:當(dāng)效率至關(guān)重要時(shí),請(qǐng)?jiān)趍ap::operator[]和map::insert之間謹(jǐn)慎做出選擇
map::operator[]的設(shè)計(jì)目的是為了提供“添加和更新”的功能;
在作為“添加”操作時(shí),insert比operator[]效率高;
當(dāng)作為“更新”操作時(shí),優(yōu)先使用operator[]
第二十五條:熟悉非標(biāo)準(zhǔn)的散列表
非標(biāo)準(zhǔn)的散列表:hast_set、hast_multiset、hash_map、hash_multimap
注意這里說(shuō)的是舊版本的STL
第二十六條:iterator優(yōu)先于const_iterator、reverse_iterator及const_reverse_iterator。
原因:
1、容器中的instert和crase函數(shù)的形參只接受iterator類型,不接受const_iterator、reverse_iterator及const_reverse_iterator。
2、從iterator到const_iterator,或者從reverse_iterator到const_reverse_iterator之間都存在隱式轉(zhuǎn)換,但是反過(guò)來(lái)技術(shù)上可以實(shí)現(xiàn),但不推薦,效率不能保證。
3、在同一個(gè)表達(dá)式中混用iterator和const_iterator,比如比較操作,會(huì)發(fā)生隱式轉(zhuǎn)換,有時(shí)會(huì)出現(xiàn)問(wèn)題。
第二十七條:使用distance和advance將容器的const_iterator轉(zhuǎn)換成iterator
distance:用于取得兩個(gè)迭代器之間的距離;
advance:用于將一個(gè)迭代器移動(dòng)指定的距離。
typedef deque<int> IntDeque;
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator ConstIter;IntDeque d;
ConstIter ci;
...
Iter i(d.begin()); /迭代器 i 指向容器 d 起始位置
advance(i, distance<ConstIter>(i, ci)); /注意這里指明distance所使用的類型為ConstIter
效率問(wèn)題:對(duì)于隨機(jī)訪問(wèn)的迭代器(如vector、string、deque產(chǎn)生的迭代器)而言,執(zhí)行時(shí)間是常數(shù)時(shí)間;對(duì)于其他標(biāo)準(zhǔn)容器以及散列表的迭代器而言,執(zhí)行時(shí)間是一個(gè)線性時(shí)間,因此推薦二十六條,盡量用iterator代替const_iterator
第二十八條:正確理解由reverse_iterator的base()成員函數(shù)所產(chǎn)生的iterator的用法
1、插入操作:如果要在一個(gè)迭代器reverse_iterator ri指定的位置上插入一個(gè)新元素,則只需在ri.base()位置處插入元素即可。
2、刪除操作:如果要在一個(gè)迭代器reverse_iterator ri指定的位置上刪除一個(gè)元素,要先遞增ri,然后在調(diào)用base()函數(shù),例如:v.erase((++ri).base());
第二十九條:對(duì)于逐個(gè)字符的輸入請(qǐng)考慮使用istreambuf_iterator
對(duì)比istream_iterator,它在默認(rèn)請(qǐng)看下會(huì)跳過(guò)空白字符,并且效率低。
讀取一個(gè)文本文件的內(nèi)容到一個(gè)string對(duì)象中,推薦的方案如下:
ifstream inputFile("test.txt");
string fileData((istreambuf_iterator<char>(inputFile)), istreambuf_iterator<char>());
第三十條:確保目標(biāo)區(qū)間足夠大
對(duì)于vector、string、deque、list容器在尾部插入對(duì)象時(shí),需要使用back_inserter函數(shù);
其中deque和list容器還可以使用front_inserter在頭部插入對(duì)象。
為了提供插入操作的性能,對(duì)于vector和string容器可以使用reserve來(lái)提前分配好內(nèi)存。
第三十一條:了解各種與排序有關(guān)的選擇
按照性能由高到底排序:
1、partition:把滿足特定條件的元素放到前面;
2、stable_partition:把滿足特定條件的元素放到前面,并且是穩(wěn)定的排序(在遇到相等的對(duì)象時(shí),還會(huì)按照出場(chǎng)順序排序);
3、nth_element:找出部分最優(yōu)的對(duì)象,可以不按照順序,比如列出前十個(gè),而且這十個(gè)可以不用排序;
4、partial_sort:部分排序;
5、sort:全部排序
6、stable_sort:穩(wěn)定版本的全部排序,不僅全部排好序,而且在遇到相等的對(duì)象時(shí),還會(huì)按照出場(chǎng)順序排序。
注意:list::sort是穩(wěn)定排序。
第三十二條:如果確實(shí)需要?jiǎng)h除元素,則需要在remove這一類算法之后調(diào)用erase
注意:remove不能刪除容器中元素。
因?yàn)閺娜萜髦袆h除元素的唯一方法是調(diào)用該容器的成員函數(shù),而remove并不知道它操作的元素所在的容器,所以remove不可能從容器中輸出刪除元素。
remove實(shí)際功能:把不用被刪除的元素放到容器前部,把需要被刪除的元素放到容器尾部。
如果需要真正刪除元素,需要使用erase和remove配合
vector<int> v;
...
v.erase(remove(v.begin(), v.end(), 99), v.end());
同理unique也需要和erase配合使用。
注意:list::remove會(huì)真正刪除元素,并且比使用erase-remove配合使用更高效,list::unique也會(huì)真正刪除元素。
第三十三條:對(duì)包含指針的容器使用remove這一類算法時(shí)要特別小心
對(duì)指針容器使用erase-remove組合來(lái)刪除時(shí),很可能造成內(nèi)存泄漏。
其實(shí)在執(zhí)行remove后,還沒(méi)有執(zhí)行erase之前已經(jīng)發(fā)生內(nèi)存泄漏。因?yàn)閞emove在將不需要?jiǎng)h除的指針元素移動(dòng)到容器頭部時(shí),會(huì)覆蓋掉需要?jiǎng)h除的指針元素,造成內(nèi)存泄漏;
再執(zhí)行erase時(shí),也會(huì)造成內(nèi)存泄漏,因?yàn)檫€沒(méi)釋放內(nèi)存,就刪除了指針。
同理:remove_if和unique也會(huì)造成內(nèi)存泄漏。
解決方法有兩種:
1、使用帶有引用計(jì)數(shù)的智能指針
2、使用partition代替remove
第三十四條:了解哪些算法要求使用排序的區(qū)間作為參數(shù)
需要排序后才能使用的算法:
// 使用二分法查找的算法,需要先排序
binary_search
lower_bound
upper_bound
equal_range// 集合操作,為了提高效率(為了保證線性時(shí)間效率),需要先排序
set_union
set_intersection
set_defference
set_symmetric_defference// 合并操作,為了提高效率
merge
inplace_merge// 判斷一個(gè)區(qū)間中的所有的對(duì)象是否都在另一個(gè)區(qū)間中,為了提高效率
includes
第三十五條:通過(guò)mismatch或lexicographical_compace實(shí)現(xiàn)簡(jiǎn)單的忽略大小寫(xiě)的字符串比較
略
第三十六條:理解copy_if算法的正確實(shí)現(xiàn)
STL中包含copy的算法
copy
copy_backward
replace_copy
replace_copy_if
reverse_copy
unique_copy
remove_copy
remove_copy_if
rotate_copy
partial_sort_copy
uninitialized_copy
但是就是沒(méi)有copy_if算法,需要自己實(shí)現(xiàn)
template<typename InputIterator,typename OutputIteratortypename Predicate>
OutputIterator copy_if(InputIterator begin,InputIterator end,OutputIterator destBegin,Predicate p)
{while (begin != end) {if (p(*begin))*destBegin++ = *begin;++begin;}return destBegin;
}
第三十七條:使用accumulate或者for_each進(jìn)行區(qū)間統(tǒng)計(jì)
count:統(tǒng)計(jì)一個(gè)區(qū)間中有多少個(gè)元素;
count_if:統(tǒng)計(jì)滿足某個(gè)條件的元素個(gè)數(shù);
min_element:獲取區(qū)間中最小值;
max_element:獲取區(qū)間中最大值;
accumulate:對(duì)區(qū)間進(jìn)行自定義的操作,比如計(jì)算一個(gè)容器中字符串長(zhǎng)度的總和。
/計(jì)算和
list<double> ld;
...
double sum = accumulate(ld.begin(), ld.end(), 0.0);/ 計(jì)算容器中字符串長(zhǎng)度的總和
string::size_type
stringLengthSum(string::size_type sumSoFar ,const string& s)
{return sumSoFar + s.size();
}set<string> ss;
...//插入一些字符串
string::size_type lengthSum = accumulate(ss.begin(), ss.end(), static_cast<string::size_type>(0),stringLengthSum);
};
第三十八:遵循按值傳遞的原則來(lái)設(shè)計(jì)函數(shù)子類
1、在C和C++的標(biāo)準(zhǔn)庫(kù)函數(shù)中,如果需要函數(shù)作為參數(shù),需要使用函數(shù)指針,并且函數(shù)指針是按值傳遞的(被復(fù)制);
2、在STL中,函數(shù)對(duì)象在函數(shù)之間來(lái)回傳遞也是按值傳遞(被復(fù)制);
3、因?yàn)楹瘮?shù)對(duì)象是按值傳遞,即需要來(lái)回復(fù)制,因此函數(shù)對(duì)象要盡可能的小;
4、函數(shù)對(duì)象必須是單態(tài)的(不能是多態(tài)),也就是說(shuō),它們不能有虛函數(shù),因此在傳遞過(guò)程中,會(huì)出現(xiàn)剝離問(wèn)題(slicing problem):在對(duì)象復(fù)制過(guò)程中,派生部分可能會(huì)被去掉,而僅保留了基類部分。
第三十九:確保判別式是“純函數(shù)”。
1、判別式函數(shù)(predicate function):是一個(gè)返回值為bool類型(或者可以隱式地轉(zhuǎn)換為bool類型)的函數(shù)。
2、判別式類(predicate class):是一個(gè)函數(shù)類,它的operator()函數(shù)是一個(gè)判別式。
3、純函數(shù)(pure function):是指返回值僅僅依賴于其參數(shù)的函數(shù)。
4、在STL中容器使用的比較函數(shù)都是判別式,比如:find_if以及各種與排序相關(guān)的算法,這些算法要求每執(zhí)行一次都要保證結(jié)果是唯一,不會(huì)受其他參數(shù)的干擾,比如全局變量、靜態(tài)變量等。
第四十條:若一個(gè)類是函數(shù)類,則應(yīng)使它可配接
1、STL函數(shù)配接器not1、not2、bind1st、bind2nd等都要求一些特殊的類型定義,提供這些必要的類型定義的函數(shù)對(duì)象被稱為可配接的(adaptable)函數(shù)對(duì)象。
2、特殊的類型定義:argument_type、first_argument_type、second_argument_type、result_type
3、繼承 std::unary_function、std::binary_function來(lái)完成上述的特殊的類型定義
第四十一條:理解ptr_fun、mem_fun和mem_fun_ref的來(lái)由
STL算法只支持非成員函數(shù),不支持成員函數(shù)(無(wú)法通過(guò)編譯),如果要使用成員函數(shù)需要使用ptr_fun、mem_fun或者mem_fun_ref來(lái)將成員函數(shù)封裝到一個(gè)函數(shù)類中
第四十二條:確保less與operator<具有相同的語(yǔ)義
1、不要特化一個(gè)位于std名字空間中的模板
2、operator<是std::less默認(rèn)實(shí)現(xiàn)方式,不要修改std::less的行為,因?yàn)檫@樣做很可能會(huì)誤導(dǎo)其它的程序員。
第四十三條:算法調(diào)用優(yōu)先于手寫(xiě)的循環(huán)
1、先看一個(gè)手寫(xiě)循環(huán)和使用算法的例子
一個(gè)支持重畫(huà)的類Widget
class Widget{
public:...void redraw() const;...
}
使用手寫(xiě)循環(huán)來(lái)重畫(huà)容器list中的所有的Widget:
list<Widget> lw;
...
for (list<Widget>::iterator i=iw.begin(); i!=iw.end(); ++i){i->redraw();
}
使用for_each循環(huán)算法來(lái)完成
for_each(lw.begin(), lw.end()),mem_fun_ref(&Widget::redray));
mem_fun_ref:封裝成員函數(shù),使它可以用在算法中,因?yàn)樗惴ㄖ荒苁褂梅浅蓡T函數(shù)
2、使用算法的優(yōu)點(diǎn)
效率高、可維護(hù)性好。
理由:略,一定要用起來(lái)
第四十四條:容器的成員函數(shù)優(yōu)先于同名的算法
1、列舉出這些函數(shù)
關(guān)聯(lián)容器:count、find、lower_bound、upper_bound、equal_range
list容器:remove、remove_if、unique、sort、merge、reverse
2、理由
速度更快、成員函數(shù)通常與容器結(jié)合的更加緊密
第四十五條:正確區(qū)分count、find、binary_search、lower_bound、upper_bound和equal_range
1、如果容器的區(qū)間是排序好的使用:binary_search、lower_bound、upper_bound和equal_range,
這些算法是對(duì)數(shù)時(shí)間的效率。
2、如果容器的區(qū)間不是排序好的使用:count、count_if、find、find_if,
這些算法是線性時(shí)間的效率。
count:區(qū)間中是否存在某個(gè)特定的值?如果存在的話,有多少個(gè)拷貝?
find:區(qū)間中有這樣的值嗎?如果有,它在哪里?
兩者還有一個(gè)區(qū)別:find找到后就返回,效率高;count要遍歷一遍容器的區(qū)間
binary_search:測(cè)試一個(gè)排序的容器區(qū)間中是否存在某一個(gè)特定的值,返回true或者false;
equal_range:查找一個(gè)值在容器區(qū)間中的位置;
lower_bound:查找一個(gè)值在容器區(qū)間中第一次出現(xiàn)的位置,如果沒(méi)有,則返回適合插入該值的位置;
第四十六條:考慮使用函數(shù)對(duì)象而不是函數(shù)作為STL算法的參數(shù)
使用函數(shù)對(duì)象比直接使用函數(shù)作為STL算法的參數(shù),更高效。
原因是:編譯器可以對(duì)函數(shù)對(duì)象做內(nèi)斂?jī)?yōu)化,而函數(shù)作為參數(shù),其實(shí)是指針,編譯器不會(huì)對(duì)指針做優(yōu)化。
第四十七條:避免產(chǎn)生“直寫(xiě)型”(wirte-only)的代碼
1、不要寫(xiě)過(guò)于復(fù)雜的嵌套函數(shù)調(diào)用
2、注意添加代碼的注釋
第四十八條:總是包含(#include)正確的頭文件
1、有些標(biāo)準(zhǔn)頭文件可以省略,也可以通過(guò)編譯,但是考慮移植性,強(qiáng)烈建議不要省略;
2、標(biāo)準(zhǔn)的STL容器都被聲明在與之同名的頭文件中:vector、list等,特殊的:multiset和set都在<set>中,map和multimap都在<map>中
3、算法被聲明在<algorithm>中,除了下面四個(gè)
4、accumulate、inner_product、adjacent_difference、partial_sum被聲明在<numeric>中
5、特殊類型的迭代器被聲明在<iterator>中
6、標(biāo)準(zhǔn)的函數(shù)類和函數(shù)配接器被聲明在<functional>中:如not1、bind2nd
第四十九條:學(xué)會(huì)分析與STL相關(guān)的編譯器診斷信息
1、std::basic_string<… …>很長(zhǎng)的一個(gè)信息,翻譯成string就好;
2、vector和string的迭代器通常就是指針,所以錯(cuò)誤的使用iterator錯(cuò)誤信息中會(huì)有:double *
3、如果錯(cuò)誤消息源于某一個(gè)STL算法的內(nèi)部實(shí)現(xiàn),那么也許在調(diào)用算法的時(shí)候,使用了錯(cuò)誤的類型。
第五十條:熟悉與STL相關(guān)的web站點(diǎn)
SGI站點(diǎn):www.sgi.com/tech/stl/
STLport站點(diǎn):www.stlport.org
Boost:www.boost.org
總結(jié)
以上是生活随笔為你收集整理的【C++】Effective STL:50条有效使用STL的经验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【C++】智能指针(一)入门
- 下一篇: 【SVN】linux下svn命令参数详解