1. 概述
最近在做性能优化,发现诸多STL误用导致的性能低下,自己也只是知道皮毛,需要系统地学习下,就从最简单的开始吧。
C++ 11 STL标准库提供了以下几种容器:
- 序列式容器:array、vector、deque、list 和 forward_list;
- 关联式容器:map、multimap、set 和 multiset;
- 无序关联式容器:unordered_map、unordered_multimap、
unordered_set 和 unordered_multiset; - 容器适配器:stack、queue 和 priority_queue。
根据容器底层采用的是连续的存储空间 or 分散的存储空间,还可以将上面容器分为如下两类:
- 采用连续的存储空间:array、vector、deque;
- 采用分散的存储空间:list、forward_list 以及所有的关联式容器和hash容器。
2. 容器的选择
STL容器的选择没有对错之分,只有合适与否,基本上可以按图索骥(详见参考文献2):
在选择容器时有以下几点需要考虑(不完全,只是给出几点例子):
- 是否需要在容器的指定位置插入新元素?如果需要,则只能选择序列式容器,而关联式容器和哈希容器是不行的;
- 是否需要容器中的元素是排序的?如果不需要,则可以考虑使用哈希容器,反之就要避免使用哈希容器;
- 是否需要使用指定类型的迭代器?如果必须是随机访问迭代器,则只能选择 array、vector、deque;如果必须是双向迭代器,则可以考虑 list 序列式容器以及所有的关联式容器;如果必须是前向迭代器,则可以考虑 forward_list 序列式容器以及所有的哈希容器;
- 当发生新元素的插入或删除操作时,是否需要避免移动容器中的其它元素?如果需要,则要避开连续内存的容器;
- 容器中查找元素的效率是否为关键的考虑因素?如果是,则应优先考虑哈希容器 > 排序的vector > 标准关联容器;
- 当只是存储而不去删除对象,或者只是操作序列中最后一个对象时,优选vector(连续内存);
- 当频繁地在序列中间做插入/删除操作时,优选list(离散内存);
- 当大多数插入/删除操作是在序列的头部和尾部时,优选deque;
- 如果是key-value形式的,可以使用map,但是map的key是唯一的;
- 如果要获取一组不重复的元素,将它们放入一个set即可,且是排序的。
3. 总结
总之,要根据业务场景选择合适的容器,以达到事半功倍的效果。
4. 参考文献
- Scott Meyers, Effective STL
- 江南-一苇渡江,如何选择合适的STL容器,https://blog.csdn.net/wangshubo1989/article/details/51172747