在用string做字符串拼接時,會發現隨着string的增大越來越慢,原因主要是string(和vector)是基於現行內存的數據結構,在海量數據時,經常會申請新的一塊內存,把原有的數據拷貝過去然后再析構掉,這樣非常浪費時間,使用reserve可以有效的改變這種情況
因為string(和vector)的reserve最大的用處是為了避免反復重新分配緩沖區內存而導致效率降低,或者在使用某些STL操作(例如std::copy)之前保證緩沖區夠大。在面對大數據量時,應該先調用 reserve(size) 進行內存的預分配(這里 size 是預估的vector元素個數)
std::accumulate的用法
vector<string> vec = { "hello", " ", "world" }; string s = accumulate(vec.begin(), vec.end(), s);
基本用法
先看一個使用accumulate的簡單例子:
vector<int> vi{1, 2, 3};
cout << accumulate(vi.begin(), vi.end(), 0); // 6
這個例子中,accumulate接收了三個參數,一對迭代器用來標識開始和結束區間,第三個參數0,是accumulate操作的初始值. accumulate遍歷[begin, end)這個區間,把每個值累加到0這個初始值上面,並最終返回累加結束的值(0 + 1 + 2 + 3) == 6.
通用用法
第一個例子只是accumulate特例的情況,其實它不僅僅能完成累加操作,它更一般的含義, 我覺得可以這樣理解:
給定一個區間和初值init以及一個可選的操作函數op,返回一個和init一樣類型的結果,該結果是通過對給定區間內的每個元素逐個累積用op操作作用於init而得到的。
另附如string 線性內存分配的缺陷
STL的string(basic_string)的缺陷
歸納起來,STL的string類主要有以下這些爭議點:
- 接口過多且規格和其他STL容器沒有達成很好的一致性。例如,string::find使用下標,而不是以iterator作為迭代位置,這和其他容器不太一樣。
- 內存碎片。由於過於頻繁的字符串構造、析構,導致系統的內存碎片現象嚴重。
- Copy-On-Write與多線程安全。string(basic_string)基於Copy-On-Write技術的原因,是因為 string的賦值被設計成為低開銷的。但是一旦考慮到多線程安全問題,Copy-On-Write會把大量的時間花在鎖的開銷上。一些新的STL實現 (如SGI STL)放棄了基於Copy-On-Write的string實現。
盤點StdExt的字符串類:String/StringBuilder/TextPool/Rope
為什么我們需要這么多的字符串類?一個原因:字符串處理的應用環境很復雜,需要因地制宜,指望一個string類行遍天下是不可能的。
從支持的串的規模來講,String/StringBuilder重點解決小字符串的問題(特別是StringBuilder,在大字符串情形下,一定會有性能瓶頸)。而TextPool, Rope重點解決巨型字符串的問題。
從實現上來講,String/StringBuilder是線性內存的。而TextPool, Rope的字符串並不物理連續,它們是邏輯字符串。
從支持的操作來講,String是常字符串;StringBuilder/TextPool主要支持改寫(set)、添加(append)操作,但不推薦插入(insert)操作,從伸縮性來講,TextPool好要好於StringBuilder;而Rope的操作側重點在於優化字符串級的復雜操作,如取子字符串、插入、刪除等,但是單個字符的修改和獲取代價略高(相比於String/StringBuilder/TextPool)。