[C++ Template]深入模板--实例化

本文深入探讨了C++模板的实例化,包括On-Demand实例化、延迟实例化和C++的实例化模型。详细解释了两阶段查找、POI(Point of Instantiation)的概念,并通过例子展示了模板实例化的过程。同时提到了显式实例化的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

第10章 实例化

10.1 On-Demand实例化

10.2 延迟实例化

10.3 C++的实例化模型

10.3.1 两阶段查找

10.3.2 POI

10.3.5 例子

10.5 显式实例化


第10章 实例化

模板实例化是一个过程, 它根据泛型的模板定义, 生成(具体的) 类型或者函数。 在C++中, 模板实例化是一个很基础的概念, 但却多少有一些错缩复杂。 复杂性的一个主要原因在于: 对于产生自模板的实体(指具体类型或函数) , 它们的定义已经不再局限于源代码中的单一位置。 事实上, 模板本身的位置、 使用模板的位置、 定义模板实参的位置都会对这个(产生自模板的) 实体的含义产生一定的影响。

 

10.1 On-Demand实例化

当C++编译器遇到模板特化的使用时, 它会利用所给的实参替换对应的模板参数, 从而产生该模板的特化。 这个过程是编译器自动进行的, 并不需要客户端代码来引导(或者不需要模板定义来引导) 。 而且, on-demand实例化的这个特性也使得C++模板和其他编译型语言的相似功能大有区别。 另外, on-demand实例化有时也被称为隐式实例化或者自动实例化

on-demand实例化表明: 在使用模板(特化) 的地方, 编译器通常需要访问模板和某些模板成员的整个定义(也就是说, 只有声明是不够的) 。 考虑下面这个包含短小源代码的文件:

template<typename T> 
class C;//(1)这里只有声明

C<int>* p = 0; //(2)正确:并不需要C<int>的定义

template<typename T>
class C 
{
    public:
    void f(); //(3) 成员声明
}; //(4) 类模板定义结束

void g (C<int>& c) //(5) 只使用类模板声明
{
    c.f(); //(6) 使用了类模板的定义
} // 需要C::f()的定义

在源代码的(1) 处, 只有模板声明是可见的, 也就是说: 模板定义此时还不是可见的(这类声明有时也被称为前置声明) 。 与普通类的情况一样, 如果你声明的是一个指向某种类型的指针或者引用(如(2) 处的声明) , 那么在声明的作用域中, 你并不需要看到该类模板的定义。例如, 声明函数g的参数类型并不需要模板C的完整定义。 然而, 如果(某个组件) 期望知道模板特化的大小, 或者访问该特化的成员, 那么整个类模板的定义就需要位于作用域中; 这也是源代码的(6) 处需要模板定义的原因。 因为如果看不见这个模板定义的话, 编译器就不能确定成员f存在且是可访问的(就是说, 不是私有的, 也不
是受保护的) 。

下面是另一个需要进行(前面的) 类模板实例化的表达式, 因为编译器需要知道C<void>的大小:

C<void>* p = new C<void>;

在这个例子中, 实例化是必不可少的, 因为只有进行实例化之后,编译器才能知道C<void>的大小。 对于上面这个特殊的模板, 你可能会认为: 用任何类型的实参 X 替换参数T之后, 都不会影响模板(特化)的大小; 因为在任何情况下, C<X>都是一个空类。 然而, 编译器并不会检测它是否为空。 而且, 为了确定 C<void>是否具有可访问的缺省构造函数, 并且确认C<void>没有声明私有的operator new 或者operator delete, 我们需要进行实例化。

 

10.2 延迟实例化

现在就有了一个相关的问题: 模板的实例化程度是怎么样的呢? 对于这个问题, 一个模糊的回答会是: 只对确实需要的部分进行实例化。换句话说, 编译器会延迟模板的实例化。 让我们细究“延迟”在这里的具体含义。

当隐式实例化类模板时, 同时也实例化了该模板的每个成员声明,但并没有实例化相应的定义。 然而, 存在一些例外的情况: 首先, 如果类模板包含了一个匿名的 union, 那么该union 定义的成员同时也被实例化了。 另一种例外情况发生在虚函数身上: 作为实例化类模板的结果, 虚函数的定义可能被实例化了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值