c++ 常用STL容器使用简练总结

根据各容器的特点,作简练的总结。

array

  • 带有STL容器接口的static c-style array
  • 大小固定,无法通过增加或移除元素改变它的大小,即size()总是返回同一值
  • 提供常量时间的随机访问功能,但只有at()会检查是否越界,其他调用若越界会导致未定义的行为
  • 对于基础类型,需要初始化:std::array<int, 4> a = {},否则初值不定
  • 使用data()成员函数直接转化为c-style array,但需要注意使用c array时既有问题
vector

  • 元素间有序,支持常量时间内的随机访问,是将元素置于dynamic array中加以管理的抽象
  • 适合于总是在容器末尾增加或删除元素的情形,在中间插入或删除元素的成本很高
  • 在使用之初,就reserve()足够的内存,避免运行中内存分配,以提高效率。注意:reserve不通缩减容量,即,如果reserve的值小于capacity(),不会有任何动作
  • 如果关心空间占用,可以使用c++11提供的shrink_to_fit()缩减容量,但即使这样它也不保证capacity()==size()
  • 也可以使用swap()技巧缩减容量:std::vector<T>(v).swap(v);。注意,改变容量后所有的迭代器失效
  • vector没有提供直接删除“与某值相等”的所有元素的成员函数,可以使用算法来完成:v.erase(remove(v.begin(), v.end(), val), v.end())
  • vector与c-style array的相互转换:v.data()。与array类似,需要注意相关潜在问题
  • 特别注意vector的使用,它的特化版本使用bit存放元素,所以其reference并非真正的lvalue,iterator也并非真正的随机访问迭代器
deque

  • 采用dynamic array管理,提供随机访问,接口与vector类似
  • 主要特点是首尾两端都开放,可以快速地从首尾两端进行插入和删除
  • deque会释放不再使用的内存区块
list

  • 使用双向链表管理元素,内部结构与array/vector/deque完全不同
  • 不支持随机访问,除非按节点遍历。但访问首尾两个元素的速度很快
  • 在任意位置上的插入和删除都是常量时间内完成,该操作也不会造成其他元素的索引及迭代器失效
  • 提供了较多的操作元素的成员函数,并提供异常安全性保证,即操作若不成功,则不作任何更改
forward list(c++11)

  • c++标准描述:我们希望forward_list和你自己手写的C-style singly linked list相较之下没有任何空间或时间上的额外开销,任何性质如果与该目标相抵触,我们就放弃该性质
  • 以单链表管理元素。相对于list,它内存占用少,行动略快,但行为受限,不能走回头路
  • 只提供前向迭代器,不支持反向迭代。没有指向最末元素的指针,不提供直接处理最末尾元素的成员函数
  • 不提供size,因为增加该性质会增加额外的开销
set/multiset

  • 会根据特定的排序准则自动将元素排序。set和multiset的不同之处是multiset允许元素重复,而set不允许
  • 排序采用“等价性”原则,默认为less,区分less和equal是必要的
  • 通常采用平衡二叉树存储,它具有良好的查找性能(logn),但自动排序造成了一个限制:不通直接改变元素的值,因为这会打乱原本正确的顺序
  • 特别提供了用于查找的成员函数,它们比通用算法中相同功能的函数效率更高
map/multimap

  • 管理kye/value pair元素,根据key排序准则自动排序。map不允许重复的key,而multimap允许
  • 与set一样,使用平衡二叉树存储,可以把set看成是key和value是同一对象的map
  • 同样,不通直接修改key的值。另外,它也提供了用于查找的成员函数,效率较高
  • 注意,使用erase()删除元素时,会使迭代器失效。应利用c++11中erase返回一个指向其后继元素迭代器的性质避免错误
  • 注意下标操作与成员函数方式的区别,下标操作通常会先构造再赋值,效率略低,且易引用不易察觉的问题
无序容器(unordered_)

  • 包括unordered_set/unordered_multiset/unordered_map/unordered_multimap。它不会以某个规则排序,而是“随意顺序”
  • 一般以链式hash表为基础,查找效率较高。但是当允许元素重复的容器且重复值较多时,可能导致效率下降
小结

使用何种容器没有绝对的标准,但选用适当的容器确实有助于提高程序性能。

当需要处理的元素数量很少时,线性算法通常对元素本身的处理过程更快。

一般规则如下:

  • 优先选用vector,它内部结构简单,允许随机访问,处理速度也快
  • 经常在数据头部和尾部增加删除元素的情况,使用deque。当元素被删除时,它能自动缩减内部内存使用量,对内存使用敏感时可以考虑
  • 经常在数据中部增删元素时,使用list。它还可以在常量时间内将元素从A容器转移到B容器
  • 经常需要根据某准则查找元素时,使用set/unordered_set
  • 需要处理key-value时,使用map/unordered_map

有时候,在特定的环境下,需要测试才能发现真正高效的容器。对于效率的极致追求者,这些付出是值得的。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值