41、了解隐式接口和编译期多态
类和模板都支持接口和多态,对类而言,接口是显式的,以函数签名为中心,多态通过虚函数发生于运行期。
对模板参数而言,接口是隐式的,基于有效的表达式,多态通过模板具现化和函数重载解析发生于编译期。
42、了解typename的双重意义
作为模板参数,class和typename没有不同,可以互换。
当使用一个内嵌类型时,需要在前面加上typename,编译器才知道它是一个类型而不是成员或者函数。1
2
3
4
5template<typename T>
void Sample(T t){
typename std::iterator_traits<T>::value_type temp(T);
...
}
43、学习处理模板化基类内的名称
因为基类模板可能被特化不提供基类模板的某个函数,所以在派生类里面直接调用模板基类的函数无法通过编译,可以通过this指针和using声明或者基类作用域符号来告诉编译器假定该函数存在。
44、将与参数无关的代码抽离templates
模板生成多个类和函数,所以任何模板都不该与某个造成膨胀的模板参数产生相依关系。
用函数参数或者class成员变量代替模板参数可以消除这种膨胀。
还可以让具有完全相同的二进制表述的类型共享实现码,也可以减小膨胀,如int和long在一些机器上是一样的,所有指针类型都是一样的。
45、运用成员函数模板接受所有兼容类型
泛化构造函数可以使一个类型隐式转换成另一个类型:1
2
3
4
5
6
7
8
9
10template<class T>
class shared_ptr{
public:
...
template<class Y>
shared_ptr(shared_ptr<Y> const&); //泛化构造函数
templa<class Y>
shared_ptr& operator=(shared_ptr<Y> const&); //泛化赋值函数
}
声明了泛化构造函数还是需要声明正常的构造函数和赋值函数。
46、需要类型转换时请为模板定义非成员函数
当提供与模板相关的包含参数隐式转换的函数时,将函数定义为friend并在类内实现。
47、请使用traits classes表现类型信息
traits classes,特性萃取,使得类型相关信息在编译期可用,以template内嵌typedef和偏特化实现。
如何使用traits?
- 建立一组重载函数,最后一个参数是traits的类型参数,对于不同的类型做实现。
- 另外建立一个控制函数调用上述函数,传入traits的参数,此为双层结构,在STL中非常常见。
48、认识模板元编程(TMP)
TMP可以将工作从运行期搬到编译期,从而实现更早的错误侦测和更高的执行效率。还可以被用来生成“基于政策选择组合”的客户定制代码,也可以用来避免生成对某些特殊类型并不合适的代码。1
2
3
4
5
6
7
8
9template<unsigned n>
class Factorial{
enum{value = n * Factorial<n-1>::value};
}
template<>
class Factorial<0>{
enum{value = 1};
}
49、定制new和delete
set_new_handler允许客户制定一个函数,当内存分配失败时调用这个函数进行处理。
Nothrow new只适用于内存分配,如果构造函数出现问题还是可能抛出异常。
50、了解new和delete的合理替换时机
有许多理由需要写个自定义的new和delete,包括改善性能、对heap运用错误进行调试、收集heap调试信息等。
51、编写new和delete时需固守常规
operator new应该内含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存要求,就该调用new_handler。它也应该有能力处理0bytes申请,class专属版本还应该处理“比正确大小更大的申请”。
operator delete应该在收到null指针时不做任何事情,class专属版本还应该处理“比正确大小更大的申请”。
52、写了placement new也要写placement delete
placement new只有placement delete能够delete,所以没有声明placement delete使用placement new的话会出现内存泄漏。
当在类内声明placement new和placement delete时会遮盖标准的new和delete,一种做法是将所有标准的new/delete放到一个基类里,然后要自定义new/delete的类继承这个基类,使用using声明获取标准形式。
53、不要轻忽编译器的警告
54、让自己熟悉包括TR1在内的标准程序库
C++标准库的主要机能由STL、iostream、locales组成,并包含C99标准程序库。
TR1添加了智能指针、一般化函数指针(function)、hash-based容器、正则表达式以及另外10个组件的支持。
TR1自身只是一个规范,为获得TR1提供的好处,需要一个实物,一个好的来源是Boost。
55、让自己熟悉Boost
Boost是一个社群,致力于免费、源码开放、同僚复审的C++程序库开发。Boost在C++标准化过程中扮演深具影响力的角色。
Boost提供了许多TR1组件实现品,以及其他许多程序库。