顺序容器概述
顺序容器为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值, 而是与元素加入容器时的相对位置相对应。
顺序容器包含:
这些容器都有不同的性能折中:
- 向容器添加或从容器中删除元素的代价。
- 非顺序访问容器中元素的代价。
除了固定大小的array外,其他容器都提供高效、灵活的内存管理。
string
和 vector
- 元素存储在连续的内存空间中,由于是连续存储的,所以由元素的下标来计算其地址是非常快速的。
- 在这两种容器的中间位置添加或删除元素将会十分耗时:在一次插入或删除操作之后,需要移动插入、删除元素位置之后的所有元素来保持连续存储。
- 添加一个元素时有可能还需要分配额外的存储空间,在这种情况下,每个元素都必须移动到新的存储空间。
list
和 forward_list
- 这两个容器的设计目的是令容器任何位置添加或删除操作都很快。
- 这两个容器不支持元素的随机访问,为了访问一个元素,只能遍历整个容器。
- 与
vector
、deque
和array
相比,这两个容器的额外内存开销也很大。
deque
deque
支持快速的随机访问。- 在
deque
的中间位置添加或删除元素的代价(可能)很高。但是在deque
的两端添加或删除元素都很快,与list
或forward_list
添加删除元素的速度相当。
forward_list
和 array
是C++ 标准新增加的类型
- 与内置数组相比,
array
是一种更安全、更容易使用的数组类型。 array
的大小是固定的,因此array
不支持添加和删除元素以及改变容器大小的操作。forward_list
的设计目标是达到与最好的手写的单向链表数据结构相当的性能,forward_list
没有size
操作,因为保存或计算其大小就会比手写链表多出额外的开销。而对于其它容器而言,size
保证是一个快速的常量时间操作。
注意:
新标准库容器的性能几乎肯定与最精心优化过的同类数据结构一样好,通常会更好。
确定使用哪种容器
- 通常
vector
是最好的选择,除非有更好的理由选择其他容器。 - 如果程序中有很多小的元素且额外开销很重要,则不能使用
list
或forward_list
。 - 如果程序要求随机访问元素,应使用
vector
或deque
。 - 如果程序要求在容器中间插入或删除元素,应使用
list
或forward_list
。 - 如果程序需要在头尾插入或删除元素,但不会在中间位置进行插入或删除操作,则使用
deque
。 - 如果程序只有在读取时才需要在容器中间插入元素,随后需要随机访问元素,则:
- 首先,确定是否真的需要在容器中间位置添加元素,当处理输入数据时,通常可以很容易地向
vector
中追加元素,然后再调用标准库sort
函数来重拍容器中的元素,从而避免在容器中间位置添加元素。 - 如果必须在中间位置插入元素,考虑在输入阶段就是要list,一旦输入完成,将
list
中的内容拷贝到一个vector
中。
- 首先,确定是否真的需要在容器中间位置添加元素,当处理输入数据时,通常可以很容易地向
- 如果程序既需要随机访问元素,又需要在容器中间位置插入元素,此时取决于在
list
或forward_list
中访问元素与vector
或deque
中插入、删除元素的相对性能。