C++标准程序库 - 模板基础
C++标准程序库 - 模板基础
本文是《C++标准程序库》模板相关内容的一个读书笔记,加上自己的一些理解和实践。
C++标准程序库:自修教程与参考手册 PDF中文版 下载
1.模板
STL中大量使用模板以实现一个通用的工具库,比如STL提供了很多模板容器类别。模板(template)是为“一个或多个尚未明确的型别”所编写的函数或类别。使用模板时,可以显式(explicitly)或隐式(implicitly)地将型别当作参数来传递。
有如下模板函数:
template <typename T> inline const T& max(const T& a, const T& b) { return a < b ? b : a; } |
可做如下调用:
max<int>(1, 2); max(2, 3); |
第一种方式是显式将型别作为参数传递给模板,第二种方式让编译器进行模板参数的自动推导,即模板参数的隐式传递。
2.模板的编译
通常我们将一个类的声明和定义(实现)分别编写在.h文件和.cc文件中,但是模板的声明和实现都必须放在.h文件中才能编译通过。
首先,要明确编译单元的概念。一个编译单元是指一个.cc文件和它所包含的所有.h文件,编译器将一个编译单元编译成一个.o文件。
其次,模板并非一次编译就生成出适合所有型别的代码,而是针对被使用的某个(或某组)型别进行编译。这要求在编译模板时必须先知道它的某个实例,再针对这个实例编译出相应型别的模板代码。因此,如果我们将模板的声明和实现分别写在.h和.cc文件中,编译器在处理模板的.cc文件所代表的编译单元时,实际上是不会生成目标代码的,因为编译器没有被告知模板的任何一个实例。
有如下分离的模板声明和实现:
max_temp.h
ifndef MAX_TEMP_H_ #define MAX_TEMP_H_
template <typename T> const T& max(const T& a, const T& b);
#endif // MAX_TEMP_H_ |
max_temp.cc
#include "max_temp.h"
template <typename T> const T& max(const T& a, const T& b) { return a > b ? a : b; } |
编译模板并查看生成的.o文件中的符号表:
sw@gentoo ~ $ g++ -c max_temp.cc sw@gentoo ~ $ nm max_temp.o sw@gentoo ~ $ |
可见max_temp.o中的符号表为空,即编译器并没有为模板生成任何目标代码。
如果将模板的声明和实现都放在.h文件中,并且在使用此模板的.cc文件中包含声明和实现此模板的.h文件,则编译器在处理此.cc文件时,将会得到模板的一个或多个实例,并且根据模板.h文件中的模板声明和实现为模板生成相应型别的代码。
我们将上述示例代码作如下更改:
max_temp.h
#ifndef MAX_TEMP_H_ #define MAX_TEMP_H_
template <typename T> const T& max(const T& a, const T& b);
#include "max_temp-inl.h"
#endif // MAX_TEMP_H_ |
max_temp-inl.h
#ifndef MAX_TEMP_INL_H_ #define MAX_TEMP_INL_H_
template <typename T> const T& max(const T& a, const T& b) { return a > b ? a : b; }
#endif // MAX_TEMP_INL_H_ |
main.cc
#include "max_temp.h"
int main(int argc, char* argv[]) { int m = max(1, 2); return 0; } |
编译main.cc并查看生成的.o文件中的符号表:
sw@gentoo ~ $ g++ -c main.cc sw@gentoo ~ $ nm main.o 00000000 W _Z3maxIiERKT_S2_S2_ 00000000 T main sw@gentoo ~ $ |
可以看到编译器为模板生成了目标代码。
另外,在这个示例中,我们将模板的实现编写在-inl.h文件中,并且在声明模板的.h文件的末尾包含相应的-inl.h文件。这样可以像非模板类型一样将声明和实现分离,从而得到更优雅的代码。
|
评论暂时关闭