说明:由于最近在使用STL写算法练习,所以先来把Effective STL这本短小精悍的书,过一遍,让自己对STL理解更深一点,选择更合适的容器,能把代码写得规范一点
第1条:慎重选择容器类型
1.容器的分类
(1)C++标准库的分类
注意:array和forward_list,无序容器都是C++11引入的新标准(《参考C++Primer第五版》),我此处将不再使用《Effective STL》中作者的分类
(2)作者的分类
连续内存容器:array,vector,string,dequeue,rope
元素存放在一块或多块(动态分配的)内;
每块内存中存有多个元素;
当有新元素插入或已有元素被删除时,同一内存块中的其他元素要向前或向后移动,为新元素让出空间,或填充被删除元素所留下的空隙
这种移动影响效率和异常安全性
基于节点的容器:list,forward_list,关联容器(包括有序和无序,有序容器的实现方式是平衡树,哈希容器使用其他基于节点的实现)
每个(动态分配的)内存块存放一个元素;
容器中元素的插入或删除只影响到指向节点的指针,而不影响节点本身的内容,所以当有插入和删除操作时,元素的值不需要移动
2.作者的建议
(1)如果需要在容器的任意位置插入新元素,就选用序列容器,关联容器做不到
(2)如果不关心容器中的元素是排序的,则可以使用无序关联容器,否则,避免使用无序关联容器
(3)如果选择的容器是标准C++的一部分,就避免使用rope
(4)如果需要使用随机访问迭代器,则对容器的选择就被限定为vector,dequeue,string;
如果需要使用双向迭代器,就避免使用forward_list和哈希容器中的一个常见实现
(5)当发生元素的插入和删除是,避免移动容器 中原来的元素很重要的话,避免使用连续内存的容器
(6)容器中的数据布局如果需要和C兼容,那就只能选择vector
(7)如果元素查找的速度是关键的考虑因素,就要考虑使用无序关联容器,排序的vector,有序的关联容器
(8)如果介意容器内部使用引用计数技术,就避免使用string和rope,可以考虑使用vector<char>
(9)如果对于插入和删除操作,需要使用事物语义(回滚的能力),那么需要使用基于节点的容器;
如果对多个元素的插入操作需要事物语义,需要选择list,对于希望编写异常安全代码的程序员,事物语义尤其重要
(10)需要使迭代器,指针或引用变为无效的次数最少的话,就要使用基于节点的容器,对于这类容器,只有迭代器,指针,引用指向了一个你正在删除的元素才会失效
(11)swap操作会使string和array迭代器,指针和引用变为无效
(12)如果序列容器的迭代器是随机访问类型,而且只要没有删除操作发生,且插入操作发生在容器的末尾,则指向数据的指针和引用就不会变为无效,这种情形选择deque,deque是唯一的,迭代器可能变为无效但指针和引用不会变为无效的STL标准库容器
3.作者提到的概念补充(待补充链接)
(1)rope
(2)引用计数技术
(3)事物语义