函数模板的实例化时机与隐式/显式实例化
C++函数模板是在什么时候实例化的?隐式实例化(Implicit Instantiation)和显式实例化(Explicit Instantiation)有什么区别?什么是模板的两次名称查找(Two-Phase Name Lookup)?
回答
古法程序员
实例化时机:函数模板在实际调用时实例化。编译器遇到调用表达式时,根据实参类型推导模板参数,生成具体函数。
隐式实例化:
template<typename T> void f(T x) { ... }
f(42); // 编译器隐式生成f<int>(int)
f(3.14); // 编译器隐式生成f<double>(double)
实例化发生在翻译单元中第一次使用处。
显式实例化:
template void f<int>(int); // 显式告诉编译器生成f<int>
// 或
extern template void f<int>(int); // C++11: 阻止在此TU隐式实例化
用于:
- 将模板实现放在.cpp中减少编译时间
- 控制模板代码膨胀
- 提供有限集合的模板参数实例化
两次名称查找(Two-Phase Lookup):
- 第一阶段(模板定义时):查找非依赖名称(不依赖模板参数的名称)
- 第二阶段(模板实例化时):查找依赖名称(依赖模板参数的名称,发生在实例化上下文中)
template<typename T>
void f(T x) {
g(42); // 第一阶段查找——调用全局g或报错
h(x); // 第二阶段查找——实例化时才确定
}
注意:成员函数模板不会在类模板实例化时自动实例化,仅当调用时才实例化(延迟实例化)。