Effective STL 总结

Table of Contents

容器

对于C++而言,容器是比数组功能更强大更灵活的工具,它可以动态增长或缩减,可以自己管理内存,可以自己记住包含了多少对象,它们还限定了自己所支持的操作的复杂性。对于不同情况我们需要选择不同的容器。

慎重选择容器类型

C++主要提供了一下几种类型的容器

  • 标准STL序列容器:vector, string, deque, list
  • 标准STL管理容器:set, multiset, map, multimap
  • 非标准序列容器 :slist, rope
  • 非标准关联容器 :hash_set, hash_multiset, hash_map, hash_multimap
  • 几种标准的非STL容器:bitset, valarray, stack, queue, priority_queue

在不同情况下我们需要采用不同的容器,一般情况下我们都使用vector容器。我们主要把容器以两种方法进行分类:

  • 对连续内存容器:把它的元素存放在一块或多块(动态分配)内存中,每块内存中存有多个元素。
  • 基于节点的容器:容器中元素的插入或删除只影响到指向节点的指针,而不影响节点本身的内容。

下面分别介绍在不同情况下怎么选择合适的容器:

1.在容器的任意位置插入新元素:选择序列容器。
2.是否关系容器中元素是排序的:不关心使用散列容器,关心则避免。
3.必须是标准C++一部分:不是可以考虑slist, rope。
4.需要哪种类型迭代器:
5.当发生元素的插入或删除时,避免移动原来容器元素是否很重要
6.容器中元素的布局是否需要和C兼容:
7:元素的查找速度是否是关键的考虑因素:
8:容器内部使用了引用计数技术:
9:对插入和删除操作,需要事物语义:
10:需要时迭代器,指针和引用变为无效的次数最少:
11:序列容器迭代器是随机访问类型,只有没有删除操作发生,且插入操作发生在容器末尾,则指向数据的指针和引用就不会变为无效:deque

不要试图编写独立于容器类型的代码

确保容器中的对象副本正确而高效

调用empty而不是检测size()是否为0

区间成员函数优先于与之对应的单元素成员函数

当心C++编译器最烦人的分析机制

如果容器中包含通过new操作创建的指针,切记在容器对象析构前将指针delete掉

切勿创建包含auto_ptr的容器对象

了解分配子的约定和限制

理解自定义分配子的合理用法

切勿对STL容器的线程安全性有不切实际的依赖


vector和string

vector和string优先于动态分配的数组

使用reserve来避免不必要的重新分配

注意string实现的多样性

了解如何把vector和string数据传给旧的API

使用“swap技巧”除去多余的容量

避免试图vector


关联容器

理解相等和等价的区别

为包含指针的关联容器指定比较类型

总是让比较函数在等值情况下返回false

切勿直接修改set或multiset中的键

考虑用排序的vector替代关联容器

当笑料至关重要时,请在map::operator[]与map::insert之间谨慎做出选择

熟悉非标准的散列容器


迭代器

iterator优先于const_iterator, reverse_iterator, const_reverse_iterator

使用distance和advnace将容器的const_iteator转换成iterator

正确理解由reverse_iterator的base()成员函数所产生的iterator的用法

对于逐个字符的输入请考虑使用istreambuf_iterator


算法

确保目标区间足够大

了解各种和排序有关的选择

如果确实需要删除元素,则需要在remove这一类算法之后调用erase

对包含指针的容器使用remove这一类算法时要特别小心

了解哪些算法要求使用排序的区间作为参数

通过mismatch或lexicographical_compare实现简单的忽略大小写的字符串比较

理解copy_if算法的正确实现

使用accumulate或者for_each进行区间统计


函数子,函数子类,函数及其他

遵循按值传递的原则来设计函数子类

确保判别式是”纯函数”

若一个类是函数子,则应使它可配接

理解ptr_fun, mem_fun和mem_fun_ref的来由

确保less与operator<具有相同的语义


在程序中使用STL

算法调用优先于手写的循环

容器的成员函数优先于同名的算法

正确区分const, find, binary_search, lower_bound, upper_bound和equal_range

考虑使用函数对象而不是函数作为STL算法的参数

考虑产生”直写型”的代码

总是包含正确的头文件

学会分享与STL相关的编译器诊断信息

熟悉与STL相关的Web站点