如何高效的使用STL

2021-07-23 04:42:59 字數 3648 閱讀 7251

一些容器選用法則:

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

2)如果程式必須在容器的中間位置插入或刪除元素,則應採用list容器;

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

4)如果只需要在讀取輸入時在容器的中間位置插入元素,然後需要隨機訪問元素,則可以在輸入時將元素讀入到乙個list容器中,然後對容器排序,再將排序後的list容器複製到vector容器中。

5)如果程式既需要隨機訪問,又需要在容器的中間位置插入或刪除元素,此時應當權衡哪種操作的影響較大,從而決定選擇list容器還是vector或deque容器。注:此時若選擇使用vector或deque容器,可以考慮只使用它們和list容器所共有的操作,比如使用迭代器而不是下標,避免隨機訪問元素等,這樣在必要時,可以很方便地將程式改寫為使用list容器。

如何高效的使用stl:

部分摘取:大cc 《高效的使用stl》

一 當物件很大時,建立指標的容器而不是物件的容器

1 stl基於拷貝的方式的來工作,任何需要放入stl中的元素,都會被複製。

這也好理解,stl工作的容器是在堆內開闢的一塊新空間,而我們自己的變數一般存放在函式棧或另一塊堆空間中。為了能夠完全控制stl自己的元素,為了能在自己的地盤隨心幹活,這就涉及到複製。而如果複製的物件很大,由複製帶來的效能代價也不小,對於大物件的操作,使用指標來代替物件能消除這方面的代價、

2 只涉及到指標拷貝操作, 沒有額外類的建構函式和賦值建構函式的呼叫;

//不可取:

vecttor vt1;

vt1.push_bach(mybigobj);

//可取:

vecttor vt2;

vt2.push_bach(new bigobj());

注意事項:

1 容器銷毀前需要自行銷毀指標所指向的物件;否則就造成了記憶體洩漏;

2 使用排序等演算法時,需要構造基於物件的比較函式,如果使用預設的比較函式,其結果是基於指標大小的比較,而不是物件的比較;

二 判斷容器是否為空時,使用empty()而不是size()==0,因為list的遍歷是限行時間,而size()會遍歷容器中的沒乙個元素。

三 盡量用區間成員函式代替單元素操作

使用區間成員函式有以下好處:

1 更少的函式呼叫

2 更少的元素移動

3 更少的記憶體分配

例:將v2後半部的元素賦值給v1:

//單元式操作:(差)

for (vector::const_iterator ci = v2.begin() + v2.size() / 2;

ci != v2.end();++ci)

v1.push_back(*ci)

//使用區間成員函式assign():(優)

v1.assign(v2.begin() + v2.size() / 2, v2.end());

一、vector:簡單,允許隨機儲存,資料的訪問十分靈活,在預設情況下應該使用。

1、在使用vector的時候,需要有一點注意:盡量少使用erase,因為在發生erase的時候,會發生一次拷貝,vector要保持結構的完整性,會把從操作物件後的每乙個成員都進行一次拷貝,並前移一位,但是在最後乙個成員發生移動的時候,如果成員是乙個非常規型別,會發生析構,那該成員以及該成員的拷貝都將被刪除

2、在vector使用reverse_iterator時,很多操作如erase,insert都不允許對reverse_iterator直接操作,需要建立乙個iterator(reverse_iterator.base()),然後對iterator進行操作。

3、如果想使用reverse_iterator刪除乙個容器中的乙個元素,優選方法:

vectorv;

【程式設計】stl各種容器的使用總結 // 向v插入1到5,同上

vecot::reverse_iterator ri =

find(v.rbegin(), v.rend(), 3); // 同上,ri指向3

v.erase(–ri.base()); // 嘗試刪除ri.base()前面的元素;對於vector,一般來說編譯不通過

v.erase((++ri).base()); // 刪除ri指向的元素;

// 這下編譯沒問題了!

4、關於reserve和resize的區別:

reserve只是預留出空間,並不真正的建立元素,所以並不會進行初始化。

resize後,修改容器空間,並初始化元素,這時候可以通過operator來進行操作。

vector 的 resize() 動作,會把原記憶體memset/bzero 0

5、容器clear()後記憶體釋放與否

c++ stl 的 vector 容器在 clear() 之後不會釋放記憶體,需要 swap(empty vector),這是有意為之(c++11 裡增加了 shrink_to_fit() 函式)。不要記成了所有 stl 容器都需要 swap(empty one) 來釋放記憶體。

事實上其他容器(map/set/list/deque)都只需要 clear() 就能釋放記憶體。

只有含 reserve()/capacity() 成員函式的容器才需要用 swap 來釋放空間,而 c++ 裡只有 vector 和 string 這兩個符合條件。

實際使用中,vector在小資料量(可能千以內吧)時,遍歷、查詢、新增刪除,都是很快的,完全可以選擇它。

二、deque:經常在頭部和尾部安插和移除元素,並且儲存的容量也比vector大得多。

ps.關於佇列,還有乙個queue,這個佇列和deque是有區別的,queue是對std容器的封裝,採用fifo的策略,queue沒有clear()函式,這確實會導致效率下降,相比deque,在100000級元素的清除中才會有0.5秒的差距,push()和push_back()動作基本一致,queue稍快,但是也要在10w級size的操作才會有0.01秒的區別。

三、list:如果經常在容器的中段執行安插,移除和移動元素。但是不支援隨機儲存。如果需要「每次安插不成功,便無效用」。list erase元素時,需要注意erase返回迭代器,否則list迭代器失效。即:itr=lst.erase(itr);

四、set和multiset:經常以某個準則尋找元素,可以使用「以這個準則為排序準則」的set和multiset,在大量的資料情況下,對數複雜度比線性複雜度的效果要好的多。set使用的是二叉樹,如果hash table可用,其效能比二叉樹高5-10倍,但是hash table並未提供插入元素的排序,如果需要對元素進行排序,則無法使用。

五、map和multimap:使用(key、value)的pair,使用字典,使用關聯式陣列 e.g「map[key] = value」。複雜度也是對數複雜度,這幾乎是最快的,hash也是對數複雜度。map內部是採用平衡二叉樹,hash map的查詢與資料量無關,複雜度是o(1)。

在不碰撞的前提下,hash map的查詢速度是最快的,何為「不碰撞」?所謂不碰撞,就是要有足夠好的hash函式,否則的話,可能會和鍊錶一樣,複雜度o(n)。

unorder_set/map:的效能優於map和hash map,唯一的問題就是無需排列,如果儲存的資料沒有序列要求,建議使用。查詢的效能尤其突出。

六、list容器中盡量不要使用刪除操

高效的使用STL

僅僅是個選擇的問題,都是stl,可能寫出來的效率相差幾倍 熟悉以下條款,高效的使用stl 1 stl基於拷貝的方式的來工作,任何需要放入stl中的元素,都會被複製 這也好理解,stl工作的容器是在堆內開闢的一塊新空間,而我們自己的變數一般存放在函式棧或另一塊堆空間中 為了能夠完全控制stl自己的元素...

高效的使用STL

僅僅是個選擇的問題,都是stl,可能寫出來的效率相差幾倍 熟悉以下條款,高效的使用stl 1 stl基於拷貝的方式的來工作,任何需要放入stl中的元素,都會被複製 這也好理解,stl工作的容器是在堆內開闢的一塊新空間,而我們自己的變數一般存放在函式棧或另一塊堆空間中 為了能夠完全控制stl自己的元素...

如何高效的使用 Git

昨天還是執行好好的今天就不行了。被刪了。突然出現了乙個奇怪的 bug,但是沒人知道怎麼回事。如果你出現過上面的任何一種情況,那本篇文章就是為你準備的。除了知道 git add git commit git push 之外,git 中還需要其他重要的技術需要掌握。長遠來看對我們是有幫助的。這裡我將向你...