本文是《C++标准程序库》模板相关内容的一个读书笔记,加上自己的一些理解和实践。
1.模板
STL中大量使用模板以实现一个通用的工具库,比如STL提供了很多模板容器类别。模板(template)是为“一个或多个尚未明确的型别”所编写的函数或类别。使用模板时,可以显式(explicitly)或隐式(implicitly)地将型别当作参数来传递。
有如下模板函数:
可做如下调用:
第一种方式是显式将型别作为参数传递给模板,第二种方式让编译器进行模板参数的自动推导,即模板参数的隐式传递。
2.模板的编译
通常我们将一个类的声明和定义(实现)分别编写在.h文件和.cc文件中,但是模板的声明和实现都必须放在.h文件中才能编译通过。
首先,要明确编译单元的概念。一个编译单元是指一个.cc文件和它所包含的所有.h文件,编译器将一个编译单元编译成一个.o文件。
其次,模板并非一次编译就生成出适合所有型别的代码,而是针对被使用的某个(或某组)型别进行编译。这要求在编译模板时必须先知道它的某个实例,再针对这个实例编译出相应型别的模板代码。因此,如果我们将模板的声明和实现分别写在.h和.cc文件中,编译器在处理模板的.cc文件所代表的编译单元时,实际上是不会生成目标代码的,因为编译器没有被告知模板的任何一个实例。
有如下分离的模板声明和实现:
max_temp.h
max_temp.cc
编译模板并查看生成的.o文件中的符号表:
可见max_temp.o中的符号表为空,即编译器并没有为模板生成任何目标代码。
如果将模板的声明和实现都放在.h文件中,并且在使用此模板的.cc文件中包含声明和实现此模板的.h文件,则编译器在处理此.cc文件时,将会得到模板的一个或多个实例,并且根据模板.h文件中的模板声明和实现为模板生成相应型别的代码。
我们将上述示例代码作如下更改:
max_temp.h
max_temp-inl.h
main.cc
编译main.cc并查看生成的.o文件中的符号表:
可以看到编译器为模板生成了目标代码。
另外,在这个示例中,我们将模板的实现编写在-inl.h文件中,并且在声明模板的.h文件的末尾包含相应的-inl.h文件。这样可以像非模板类型一样将声明和实现分离,从而得到更优雅的代码。