3.1
不要像重新发明车轮那样企图做每件事,去使用库。
<<Effective STL>>
包含了关于如何使用STL
的很多宝贵建议。如Item 13
解释了为什么vector
和string
优先于动态的数组。Item 43
解释了算法调用优先于手写循环。还有关于关联容器,函数对象,迭代器的用法和注意事项。用STL
写程序时可以作为参考。
3.2
不要相信奇迹,要理解你的库能做什么,它们如何做,它们做时需要多大的代价。
对STL
有了全局的,深入的了解后,才能知道它能做什么,如何做,在什么样的情况下选择什么样的容器和算法。
3.3
当你遇到一个选择时,应该优先选择标准库而不是其他的库。
C++
库有很多,如STL
,BOOST
,LOKI
,BLITZ++
,POOMA
等等。从移植性,维护性,可读性,可扩展性等方面来说,我们总是应该优先选择标准库。
3.4
不要认为标准库对于任何事情都是最理想的。
不要把标准库看成神,如标准库中的valarray
,并没有用表达式模板这样的高级技术去进行优化,所以并不是一个最优的实现。
3.5
切记#include
你所用到的功能的头文件。
标准库的功能都是通过某个像<iostream>
这样的头文件提供的。例如,要用vector
的功能就要#include<vector>
。C++
标准并没有规定标准库的各个头文件的组织关系,所以对于不同的标准库实现,头文件的组织可能会不同。打个比方,有的实现可能会在头文件<vector>
中包含find
函数,而有的却不会,所以要使用find
函数,就必须明确的包含<algorithm>
,而不能依靠#include <vector>
来完成。另外,对于<iostream>
,
如果在头文件中并没有用到流的完整定义,那么#include<iosfwd>
就可以了,它里面是一些流的声明。
<<Effective STL>> Item 48
中有这方面更详细的解释。
3.6
记住,标准库的功能定义在名字空间std
之中。
标准库的功能定义在名字空间std
之中,例如可以用std::string
来使用string
,或者用using namespace std;
使所有的std
中的名字可用,而不必加std::
前缀。但通常这种将所有名字都放入全局名字空间并不是一种好的做法。对于大程序,使用std::string
或者using std::string;
单独把string
引入全局名字空间更好。
3.7
请用string
,而不是char*
。
标准库的string
有一百多个成员函数,提供了丰富的功能,如拼接、比较、查找、替换、删除等,并且可以自动管理内存。所以使用string
会让程序更加简洁安全。无论何时,如果你在使用char*
,
请考虑是否使用string
来代替更合适。
<<Effective STL>> Item 13
解释了string
优先于字符数组。
3.8
如果怀疑,就用一个检查区间范围的向量。
下面给出了一个类Vec
,它就像是一个vector
,当下标超出区间范围,它将抛出out_of_range
异常。
template<class T> class Vec: public vector<T>{
public:
Vec() : vector<T>() { }
Vec(int s) : vector<T>(s) { }
T& operator[](int i) {return at(i);}
const T& operator[](int i) const {return at(i);}
};
这个小例子也展示了怎样继承标准库的功能。这里用了public
继承,因为Vec
和vector
符合IS-A
关系。或者用组合也可以。单独调用vector
的at
方法也可以,但要使用二维数组就不太直观,比如要访问一个元素vector<
vector <int> > v
;用v.at(i).at(j)
才可以。对于Vec<Vec<int> > v
;用v[i][j]
就可以了。
3.9 vector<T>
、list<T>
和map<key,value>
都比T[]
好。
vector<T>
、
list<T>
和
map<key,value>
要比使用
C
风格的数组更好
,
因为这样就不用去管理内存
,
并且使程序简洁、安全、高效。
<<Effective STL>> Item 13
至
Item 18
解释了
vector
优先于数组和使用
vector
的一些技巧。
3.10
如要向一个容器中添加一个元素
,
用
push_back()
或
back_inserter()
。
push_back()
在容器的最后添加元素,可以根据需要扩展内存。back_inserter()
同样在容器的最后添加元素,并根据需要扩充容器,可以方便的和算法结合使用。例如,
vector<int> v; list<int> l; copy(v,begin(), v,end(),back_inserter(l) );
<<Effective STL>> Item 30
中有这方面更详细的解释和应注意的问题。
3.11
采用对vector
的push_back()
,而不是对数组的realloc()
。
vector
的push_back()
可以根据需要扩展内存,这是在容器内部自动完成的,而不像realloc()
要提供额外的参数,从而push_back()
更安全。方便。
3.12
在main()
中捕捉公共的异常。
可以让main()
以一个try
块作为主体,从而使异常所造成的奇怪现象最小化,例如,
int main()
try{
//your code
}
catch(…)
{
cerr << “unknown exception thrown./n”;
}