STL容器选择
注:這是篇搬運工文章,是在讀了《Effective STL》這本書后對一些知識點的總結、摘錄,希望和大家一起學習共享。
題外話:在網上看到很多人噴C++,噴STL,其實我曾經也會噴C#、噴Java,...但是隨著工作經驗的增長,閱讀書籍的增多,知識面的擴展,我對種類繁多的語言以及技術產生的是敬畏,再也不敢也不會信口開河的去噴,每種語言都有自己的優缺點,也正是這些優缺點,決定了其適用場景。送大家一句今天剛看到的話“工程師會思考項目用什么語言好,碼農會思考哪種編程語言不好”。
經常聽到有人抱怨STL性能不好,不排除你的公司十分牛X而且對性能要求極高,至少我想絕大多數企業和工程師自己寫不出比STL更好的庫,如果你不相信,請先看看《STL源碼剖析》這本書。我想大多數情況是你沒有選擇對相應的容器和沒有正確的使用。
容器分類
標準STL序列容器:vector,string,deque,list;
標準STL關聯容器:set,multiset,map,multimap;
非標準關聯容器(基于散列表):hash_set,hash_multiset,hash_map,hash_multimap;
連續內存容器:vector,string,deque;
基于節點的容器:list,標準STL關聯容器;
主要容器分析
連續內存容器(也叫做基于數組的容器)在一個或多個(動態分配)的內存塊中保存它們的元素。如果一個新元素被插入或者已存元素被刪除,其他在同一個內存塊的元素就必須向上或者向下移動來為新元素提供空間或者填充原來被刪除的元素所占的空間。這種移動影響了效率和異常安全;
基于節點的容器在每個內存塊(動態分配)中只保存一個元素。容器元素的插入或刪除只影響指向節點的指針,而不是節點自己的內容。所以當有東西插入或刪除時,元素值不需要移動。
容器選擇
vector、list和deque提供給程序員不同的復雜度,因此應該這么用:vector是一種可以默認使用的序列類型,當很頻繁地對序列中部進行插入和刪除時應該用list,當大部分插入和刪除發生在序列的頭或尾時可以選擇deque這種數據結構。
你需要“可以在容器的任意位置插入一個新元素”的能力嗎?如果是,你需要序列容器,關聯容器做不到。
你關心元素在容器中的順序嗎?如果不,散列容器就是可行的選擇。否則,你要避免使用散列容器。
你需要哪一類迭代器?如果必須是隨機訪問迭代器,在技術上你就只能限于vector、deque和string。
當插入或者刪除數據時,是否非常在意容器內現有元素的移動?如果是,你就必須放棄連續內存容器。
容器中的數據的內存布局需要兼容C嗎?如果是,你就只能用vector。
查找速度很重要嗎?如果是,你就應該看看散列容器(優于)排序的vector(優于)標準的關聯容器大概是這個順序。
你需要插入和刪除的事務性語義嗎?也就是說,你需要有可靠地回退插入和刪除的能力嗎?如果是,你就需要使用基于節點的容器。如果你需要多元素插入的事務性語義,你就應該選擇list,因為list是唯一提供多元素插入事務性語義的標準容器。事務性語義對于有興趣寫異常安全代碼的程序員來說非常重要。
你要把迭代器、指針和引用的失效次數減到最少嗎?如果是,你就應該使用基于節點的容器,因為在這些容器上進行插入和刪除不會使迭代器、指針和引用失效(除非它們指向你刪除的元素)。一般來說,在連續內存容器上插入和刪除會使所有指向容器的迭代器、指針和引用失效。
你需要具有有以下特性的序列容器嗎:1)可以使用隨機訪問迭代器;2)只要沒有刪除而且插入只發生在容器結尾,指針和引用的數據就不會失效?這個一個非常特殊的情況,但如果你遇到這種情況,deque就是你夢想的容器。(有趣的是,當插入只在容器結尾時,deque的迭代器也可能會失效,deque是唯一一個“在迭代器失效時不會使它的指針和引用失效”的標準STL容器。)
總結
- 上一篇: 宽度高度sizeWithFont:con
- 下一篇: 软件能力[置顶] 程序员如何成为设计师,