日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《Effective STL》学习笔记(第二部分)

發布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Effective STL》学习笔记(第二部分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2、 vector和string

所 有的STL容器都很有用,但是相比于其他容器,vector和string更常用。本章從多個角度覆蓋vector和string,如:為什么提倡使用 vector代替數組,怎樣改進vector和string的性能?怎樣除去過剩的內存,vector<string>是個什么東西?……

條款13:盡量使用vector和string來代替動態分配的數組

使 用vector和string代替動態分配的數組是個很明智的選擇,它們不僅能夠自動管理內存(主要是自動釋放內,自動增加內存),還提供了很多可用的函 數和類型:既有像begin、end和size這樣的成員函數,也有內嵌的像iterator、 reverse_iterator或value_type的typedef。

對于string實現,可能使用了引用計數器,這是一種那個消 除了不必要的內存分配和字符拷貝的策略,而且在很多應用中可以提高性能。但這種方案在多線程環境下可能會嚴重降低性能,可能的解決方法是:(1)關閉引用 計數(如果可能的話) (2)尋找或開發一個不使用引用計數的string實現(或部分實現)替代品 (3)考慮使用vector<char>來代替string,vector實現不允許使用引用計數,所以隱藏的多線程性能問題不會出現了

條款14:使用reserve避免不必要的重新分配

reserve成員函數允許你最小化必須進行的重新分配的次數,因而可以避免真分配的開銷和迭代器/指針/引用失效。

● size()返回容器中已經保存的元素個數

● capacity()返回容器可以保存的最大元素個數。如果要知道一個vector或string中有多少沒有被占用的內存,可以讓capacity() 減去size();如果size和capacity返回同樣的值,容器中就沒有剩余空間了,而下一次插入(通過insert或push_back等)會引 發重分配。

● resize(Container::size_type n)強制把容器改為容納n個元素。調用resize之后,size將會返回n。如果n小于當前大小,容器尾部的元素會被銷毀。如果n大于當前大小,新默認 構造的元素會添加到容器尾部。如果n大于當前容量,在元素加入之前會發生重新分配。

● reserve(Container::size_type n)強制容器把它的容量改為至少n,提供的n不小于當前大小。這一般強迫進行一次重新分配,因為容量需要增加。(如果n小于當前容量,vector忽略 它,這個調用什么都不做,string可能把它的容量減少為size()和n中大的數,但string的大小沒有改變。)

條款15:小心string實現的多樣性?????

條款16: 如何將vector和string的數據傳給遺留的API

我們可以將vector或者string傳遞給數組/指針類型的參數,如:

【1】 用C風格API返回的元素初始化一個vector,可以利用vector和數組潛在的內存分布兼容性將存儲vecotr的元素的空間傳給API函數:

1 2 3 4 5 6 7 8 9 // C API:此函數需要一個指向數組的指針,數組最多有arraySize個double // 而且會對數組寫入數據。它返回寫入的double數,不會大于arraySize size_t fillArray(double *pArray, size_t arraySize); vector<double> vd(maxNumDoubles); // 建立一個vector,它的大小是maxNumDoubles vd.resize(fillArray(&vd[0], vd.size())); // 讓fillArray把數據寫入vd,然后調整vd的大小 為fillArray寫入的元素個數

【2】 用C風格API的數據初始化string對象,也很簡單。只要讓API將數據放入一個vector<char>,然后從vector中將數據拷到string:

1 2 3 4 5 6 7 8 9 10 11 // C API:此函數需要一個指向數組的指針,數組最多有arraySize個char // 而且會對數組寫入數據。它返回寫入的char數,不會大于arraySize size_t fillString(char *pArray, size_t arraySize); vector<char> vc(maxNumChars); // 建立一個vector, 它的大小是maxNumChars size_t charsWritten = fillString(&vc[0], vc.size()); // 讓fillString把數據寫入vc string s(vc.begin(), vc.begin()+charsWritten); // 從vc通過范圍構造函數拷貝數據到s

【3】讓C風格API把數據放入一個vector,然后拷到你實際想要的STL容器中的主意總是有效的:

1 2 3 4 5 6 7 8 9 10 11 size_t fillArray(double *pArray, size_t arraySize); // 同上 vector<double> vd(maxNumDoubles); // 一樣同上 vd.resize(fillArray(&vd[0], vd.size())); deque<double> d(vd.begin(), vd.end()); // 拷貝數據到deque list<double> l(vd.begin(), vd.end()); // 拷貝數據到list set<double> s(vd.begin(), vd.end()); // 拷貝數據到set

【4】如何將vector和string以外的STL容器中的數據傳給C風格API?只要將容器的每個數據拷到vector,然后將它們傳給API:

1 2 3 4 5 6 7 8 9 void doSomething(const int* pints, size_t numInts); // C API (同上) set<int> intSet; // 保存要傳遞給API數據的set ... vector<int> v(intSet.begin(), intSet.end()); // 拷貝set數據到vector if (!v.empty()) doSomething(&v[0], v.size()); // 傳遞數據到API

條款17:使用“交換技巧”來修整過剩容量

實 際項目中可能遇到這樣的情況:剛開始時,將大量數據插入到一個vector中,后來隨著實際的需要,將大量元素從這個vector中刪除,這樣的 話,vector中會占用大量未使用的內存(通過函數capacity()可看到結果),如何將這些未使用的內存釋放,可采用以下幾種方法:

1 vector<Contestant>(contestants).swap(contestants);

表達式vector<Contestant>(contestants)建立一個臨時vector,它是 contestants的一份拷貝:vector的拷貝構造函數做了這個工作。但是,vector的拷貝構造函數只分配拷貝的元素需要的內存,所以這個臨 時vector沒有多余的容量。然后我們讓臨時vector和contestants交換數據,這時contestants只有臨時變量的修整過的容量, 而這個臨時變量則持有了曾經在contestants中的發脹的容量。在這里(這個語句結尾),臨時vector被銷毀,因此釋放了以前 contestants使用的內存

同樣的技巧可以應用于string:

1 2 3 4 5 string s; ... // 使s變大,然后刪除所有它的字符 string(s).swap(s); // 在s上進行“收縮到合適”

條款18:避免使用vector<bool>

作為一個STL容器,vector<bool>有兩個問題。第一,它不是一個STL容器。第二,它并不容納bool,因而永遠不要使用vector<bool>。

標 準庫提供了兩個替代品,它們能滿足幾乎所有需要。第一個是deque<bool>。deque提供了幾乎所有vector所提供的(唯一值得 注意的是reserve和capacity),而deque<bool>是一個STL容器,它保存真正的bool值。當然,deque內部內 存不是連續的。所以不能傳遞deque<bool>中的數據給一個希望得到bool數組的C API。第二個vector<bool>的替代品是bitset。bitset不是一個STL容器,但它是C++標準庫的一部分。與STL容 器不同,它的大小(元素數量)在編譯期固定,因此它不支持插入和刪除元素。此外,因為它不是一個STL容器,它也不支持iterator

3、 關聯容器

條款19:了解相等和等價的區別

set中的find函數采用的是等價準則,而find算法采用的是相等準則。

條款20:為指針的關聯容器指定比較類型

當關聯容器中保存的是對象指針時,需要自己定義比較器(不是一個函數,而是一個仿函數模板),不然關聯容器會按照指針大小進行排序,而不是指針指向的內容。

條款21: 永遠讓比較函數對“相等的值”返回false

在關聯容器中,用戶自定義比較類型時,當兩個元素相等時,應該返回false。

舉例:建立一個set,比較類型用less_equal,然后插入一個10:

1 2 3 set<int, less_equal<int> > s; // s以“<=”排序 s.insert(10); // 插入10

然后再插入一次10:

1 s.insert(10);

關聯容器對“相同”的定義是等價,因此set測試10B是否等價于10A。當執行這個測試時,它自然是使用set的比較函數。在這一例子 里,是operator<=,因為我們指定set的比較函數為less_equal,而less_equal意思就是operator<=。 于是,set將計算這個表達式是否為真:

1 !(10A <= 10B) && !(10B <= 10A) // 測試10A和10B是否等價

顯然,該表達式返回false,于是兩個10都會插入這個set,結果是set以擁有了兩個為10的值的拷貝而告終,也就是說它不再是一個set了。通過使用less_equal作為我們的比較類型,我們破壞了容器!

條款22:避免原地修改set和multiset的鍵

原地修改map和multimap的鍵值是不允許的,同時,應避免原地修改set和multiset的鍵(盡管這是允許的),因為這可能影響容器有序性的元素部分,破壞掉容器。

條款23:考慮用有序vector代替關聯容器

在你的應用中,如果查找的頻繁程度比插入和刪除的高很多,那么推薦你用有序vector代替關聯容器,這主要是從內存引用失效頻率考慮的。

用vector模擬關聯數組的代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 typedef pair<string, int> Data; // 在這個例子里 // "map"容納的類型 class DataCompare { // 用于比較的類 ?public: ??bool operator()(const Data& lhs, // 用于排序的比較函數 ???const Data& rhs) const ?{ ??return keyLess(lhs.first, rhs.first); // keyLess在下面 } bool operator()(const Data& Ihs, // 用于查找的比較函數 const Data::first_type& k) const // (形式1) { ??return keyLess(lhs.first, k); } bool operator()(const Data::first_type& k, // 用于查找的比較函數 const Data& rhs) const // (形式2) { ??return keyLess(k, rhs.first); } private: bool keyLess(const Data::first_type& k1, const Data::first_type& k2) const // “真的” 比較函數 { ??return k1 < k2; } }; vector<Data> vd; // 代替map<string, int> ... // 建立階段:很多插入, // 幾乎沒有查找 sort(vd.begin(), vd.end(), DataCompare()); // 結束建立階段。(當模擬multimap時,你可能更喜歡用stable_sort 來代替) string s; // 用于查找的值的對象 ... // 開始查找階段 if (binary_search(vd.begin(), vd.end(), s, DataCompare()))... // 通過binary_search查找 vector<Data>::iterator i = lower_bound(vd.begin(), vd.end(), s, DataCompare()); // 再次通過lower_bound查找, if (i != vd.end() && !DataCompare()(s, *i))... // 條款45解釋了“!DataCompare()(s, *i)”測試 pair<vector<Data>::iterator, vector<Data>::iterator> range = equal_range(vd.begin(), vd.end(), s, DataCompare()); // 通過equal_range查找 if (range.first != range.second)... ... // 結束查找階段,開始 // 重組階段 sort(vd.begin(), vd.end(), DataCompare()); // 開始新的查找階段...

條款24:當關乎效率時應該在map::operator[]和map-insert之間仔細選擇

STL map的operator[]被設計為簡化“添加或更新”功能,但事實上,當“增加”被執行時,insert比operator[]更高效。當進行更新 時,情形正好相反,也就是,當一個等價的鍵已經在map里時,operator[]更高效。理由如下:當進行“增加”操作時,operator[]會有三 個函數調用:構造臨時對象,撤銷臨時對象和對對象復制,而insert不會有;而對于更新操作,insert需要構造和析構對象,而operator[] 采用的對象引用,不會有這樣的效率損耗。一個較為高效的“添加或更新”功能實現如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 template<typename MapType, // map的類型 typename KeyArgType, // KeyArgType和ValueArgtype是類型參數 typename ValueArgtype> typename MapType::iterator efficientAddOrUpdate(MapType& m, const KeyArgType& k, const ValueArgtype& v) { ??typename MapType::iterator Ib = // 找到k在或應該在哪里; ??m.lower_bound(k); ??if(Ib != m.end() && // 如果Ib指向一個pair ???!(m.key_comp()(k, Ib->first))) { // 它的鍵等價于k... ??Ib->second = v; // 更新這個pair的值 ??return Ib; // 并返回指向pair的迭代器 ?} else{ ??typedef typename MapType::value_type MVT; ??return m.insert(Ib, MVT(k, v)); // 把pair(k, v)添加到m并返回指向新map元素的迭代器 ?} }

條款25:XXXXXXXXXXXXXXXXXXXX(不常用)

原創文章,轉載請注明:?轉載自董的博客

本文鏈接地址:?http://dongxicheng.org/cpp/effective-stl-part2/

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的《Effective STL》学习笔记(第二部分)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品高潮呻吟 | 国产精品无码白浆高潮 | 最近中文字幕一区二区 | 午夜伊人网 | 无码一区二区精品 | 黄片毛片在线免费观看 | 欧美狂猛xxxxx乱大交3 | 黄网在线观看视频 | 91桃色视频| 亚洲一区二区三区无码久久 | 国产福利精品在线 | 欧美绿帽合集xxxxx | 成年人晚上看的视频 | 午夜精品视频 | 激情五月av | 亚洲天堂男人的天堂 | 91亚洲专区 | 光棍天堂av | 激情一区二区三区 | 粉嫩av一区二区三区四区五区 | 日本japanese丰满白浆 | av成人免费在线 | 老司机午夜免费精品视频 | 欧美成人tv | 老司机在线免费视频 | 人体毛片 | 少妇三级全黄 | 成年人视频网站 | 尤物视频在线观看免费 | 一级片aaaa| 亚洲精品国产精品乱码不99热 | 亚洲色精品三区二区一区 | 女生张开腿给男生桶 | 97香蕉久久超级碰碰高清版 | 欧洲xxxxx | wwww黄色片| 国产午夜av | 青娱网电信一区电信二区电信三区 | 好吊色网站| 粗大的内捧猛烈进出 | 日本中文字幕在线免费观看 | 超碰美女 | 免费看欧美黄色片 | 国内精品毛片 | 激情综合网激情 | 岛国av电影在线观看 | 女性裸体下面张开 | 91色影院 | 一本色道久久综合亚洲精品图片 | 偷看洗澡一二三区美女 | 美日韩精品一区二区 | 另类在线视频 | 插插插av | 97caoporn| 日韩城人网站 | 石原莉奈在线播放 | 三上悠亚 电影 | 可以看的黄色网 | 国产午夜精品久久久 | 国产免费91视频 | 久草福利资源站 | 五月婷婷六月丁香 | 亚洲 另类 春色 国产 | 日韩毛片高清在线播放 | 精品视频一区二区在线观看 | 99久久婷婷国产综合精品草原 | 日本黄色美女网站 | 亚洲乱码一区二区三区 | 手机在线看片日韩 | 欧美36p| 国产精品mv | 小罗莉极品一线天在线 | 女人一区二区三区 | 日本aa大片 | 国产福利片在线观看 | 69久久精品无码一区二区 | 免费在线观看一区二区 | 亚洲成人黄 | 国产精品污 | 色婷婷在线影院 | 亚洲欧美综合一区 | 国产精品久久久久久妇女6080 | 手机在线看片福利 | 69精品人人人人 | 免费三片60分钟 | 中文永久免费观看 | 亚洲免费观看av | 一区二区三区在线免费观看 | 农村妇女愉情三级 | 日本亚洲一区二区三区 | 久久久久xxxx | 老子影院午夜伦不卡大全 | 欧美日韩电影一区二区三区 | 在线免费观看日韩av | 性猛交ⅹxxx富婆video | 91九色高潮 | 美女裸体网站久久久 | 日韩中文av | 久久国产精品国产精品 |