Posted on 2008-11-03 20:36
Batiliu 阅读(468)
评论(0) 编辑 收藏 引用 所属分类:
读书笔记
第一条 vector的使用
设计vector是用来代替内置数组的,因此其效率应该与内置数组一样,内置数组在下标索引(operator[])时是不进行越界检查的。如果你需要下标越界检查,可以使用at方法。
- size告诉你容器中目前实际有多少个元素,而对应地,resize则会在容器的尾部添加或删除一些元素。这两个函数对list、vector、deque都适用,但对其他容器并不适用。
- capacity则告诉你最少添加多少个元素才会导致容器重分配内存,而reserve在必要的时候总是会使容器的内部缓冲区扩充至一个更大的容量,以确保至少能满足你所指出的空间大小。这两个函数仅对vector适用。
第二条 第三条 字符串格式化
|
sprintf snprintf stringstream strstream boost::lexical_cast |
易用吗,代码清晰明确吗 高效吗,无额外内存分配吗 长度安全吗 类型安全吗 是否可以用于模板之中 |
是 是 否 否 是 是 是 否 是 否 否 是 是 是 是 否 否 是 是 是 否 否 是 是 是 |
第四条 标准库成员函数
使用标准库里面的mem_fun,将成员函数适配为仿函数(functor),从而可被标准库算法以及其他正常情况下只适用自由函数的代码所使用。但不要将它用在标准库自己身上。
第五条 第六条 泛型性的风味
// 示例:重载swap()。
class X {
public:
void swap(X&);
};
// 注意:这个重载并没有放在std名字空间当中。请参考名字空间Koenig查找。
swap(X&a, X&b) {
a.swap(b);
}
第七条 泛型性的风味
在如下代码中,最后一行代码调用的是f()的那个版本?
// 示例:函数特化。
template <typename T> // (a):一个主模板
void f(T);
template <typename T> // (b):一个主模板,重载了(a)
void f(T*);
template <> // (c):(a)的一个显示特化(全特化)
void f<int*>(int*);
template <> // (d):(b)的一个显示特化(全特化)
void f<int>(int*);
// ....
int * p;
f(p); // 调用的哪个版本?
答案是……调用(d),想必结果是你意料之中。如果我们注释掉(d),f()调用的又是哪个版本呢?答案是……调用(b),是不是让你大吃一惊?如果这令你感到惊讶的话,你并不是唯一一个,当时它曾让许多专家大吃一惊。理解这个例子的关键其实很简单:模板特化并不参加重载。
让我们来看看函数模板的重载规则。
- 非模板函数是C++中的一等公民。如果一个普通的非模板函数跟一个函数模板在重载解析的参数匹配中表现一样好的话,编译器会选择普通函数。
- 如果编译器没有发现合适的一等公民,那么主函数模板作为C++中的二等公民就会被纳入考虑。具体选择哪个主函数模板则取决于哪个的参数类型匹配的最好。
- 如果这个被选中的主函数模板碰巧有针对所使用的模板实参做了特化的话,该特化版本才会被编译器选中。否则编译器将使用以正确类型实例化的主模板。
- 等等
// 示例:函数特化。
template <typename T>
struct X;
template <typename T> // 请不要动这个函数
void f(T t) { X<T>::far(t); }
template <typename T> // 可以对这个函数进行特化
struct X {
static void f(T t);
};
第八条 友元模板
// 示例:友元模板。
namespace boost {
template <typename T> void checked_delete(T* x);
}
class Test {
friend void boost::checked_delete<Test>(Test* x); // 或"checked_delete<>(Test* x)"
}
第九条 第十条 导出限制
第十一条 第十二条 异常安全问题