By Herb Sutter, Andrei Alexandrescu树人 译STL:容器
76. 默认情况下使用vector。否则,选择一个适当的容器。
使用“正确(合适)的容器”是很重要的:如果你有一个很好的理由使用某个特定的容器,在你了解你所做的是对的情况下,你可以使用那个容器。
So is using vector: Otherwise, write vector and keep going without breaking stride, also knowing you did the right thing.
77. 用vector和string替代数组。
Why juggle Ming vases?避免用C风格数组,指针运算和内存管理原语来实现数组抽象。使用vector和string不仅更容易,而且有助于写出更安全和伸缩性的软件来。
78. 用vector(和string::c_str)和非C++ API交换数据。
vector在转换过程中并没有丢失。vector isn't lost in translation:vector和string::c_str是你与非C++ API之间通信的网关。但不要认为iterator就是指针;要得到一个由vector<T>::iterator iter引用的元素的地址,可以使用&*iter。
79. 只把值和智能指针放到容器中。
把值对象存放在容器中:容器总是假定包含的是类值类型(value-like类型),包括值类型(直接持有),只能指针和迭代器(iterator)。
80. 优先使用push_back来扩充一个序列。
尽量使用push_back:如果你不需在意插入的位置,优先使用push_back来给一个序列增添一个元素。其他方法则可能是非常慢和不清晰的。
81. 对单元素操作优先使用范围操作。Prefer range operations to single-element operations.
Don't use oars when the wind is fair:给序列容器添加元素时,优先使用范围操作(例如:带一对迭代器参数的insert形式),而不是一系列单元素形式的操作的调用。通常调用范围操作的代码易于编写和阅读,而且比显式循环更有效。(参见:Item84)
82. 使用公认的习惯用法来真正地收缩容量和删除元素。
Use a diet that works:为了真正地体现容器的额外能力,可以使用“swap trick”。要真正从一个容器中清除元素,可以使用erase-remove惯用法。
STL:算法
83. 使用安全的(被验证过的)STL实现。
安全第一(参见:Item6):使用一个安全的STL实现,即使它只适用于你的编译器平台中的一个;即使它只是一个还在测试中的预发布版本.
84. 优先调用算法,而不是手写的循环。
明智地使用函数对象:对于每个简单的循环,手写的循环可能是最简单也是最有效的解决方法。但是用算法代替手写的循环可能更具表现性和可维护性,更不容易出错,而且也很有效。
当调用算法时,编写你自己的函数对象来封装你需要的逻辑。避免把参数邦定和简单的函数对象夹杂在一起。(例如:bind2nd,plus),这往往会降低清晰性.考虑试试[Boost]Lambda程序库,它把编写函数对象的任务自动化了.
85. 使用正确的STL搜索算法。
搜索(刚刚够就好):合适的搜索可能就是STL了(比光速慢),但它仍是非常快的:这一点应用于在一个范围内搜索一个特定的值,或者定位所在的位置。要搜索一个未排序的范围,使用find/find_if或count/count_if。要搜索一个排序过的范围,使用lower_bound, upper_bound, equal_range, 或者 (很少) binary_search。(不管binary_search的通用名字,它通常都不是好的选择。)
86. 使用正确的STL排序算法。
排序(刚刚够就好):理解各个排序算法,适用你所需要的代价最小的算法。
87. 判定纯函数。
判定纯度:一个函数对象的判定是一个返回是或不是的答案,像一个bool类型的值。凭数学感觉,如果一个函数的结果只依赖于它的参数,那么它就是纯的(注意这里的“纯”和纯虚函数没有任何关系)。
88. 优先使用函数对象作为算法和比较器的参数,而不是函数。
对象比函数更好插入:对于算法,优先使用函数对象来做参数,而不是函数。关联容器的比较器则必须是函数对象。函数对象是可适应的,而且违反直觉的是,它可以产生出比函数更快的代码。
89. 正确地编写函数对象。
廉价的,适应性强的:设计拷贝代价低廉的函数对象。只要可能,可以通过从unary_fuction和binary_function派生来生成适应性强的函数对象。