栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++模板编程(18)---模板实例化instantiation

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++模板编程(18)---模板实例化instantiation

Template实例化instantiation是由泛化的template定义式产生出实际类型和函数的过程。C++template实例化是一个基础而复杂的概念。说它复杂的一个原因是,由template产生的物体entities的定义不限于源码的某一单独位置上。template所在位置、template被使用位置、以及template argument定义位置,都在构成物体意义一事上扮演各自的角色。

本文·讲述如何组织我们的程序代码才能以正确方式运用template。我们还将讲述为解决实际实例化问题,大多数流行的C++编译器所使用的方法,尽管这些方法应该是语义等价的。

1. 随需实例化on-demand instantiation

    当C++编译器见到程序中使用一个template特化体specialization,便将template parameters替换为所需的argument,以创建出这个特化体。这个过程是自动完成,无需借助任何client程序码或template定义的指示。正是这种随需实例化的特性使得C++template机制有别于其它语言的类似机制。这种机制有时也称为隐式implicit或自动automatic实例化。

随需实例化意味着,当程序用到template时,编译器需要得知该template和其某些成员的完整定义(而不仅仅是template的声明)。考虑下面的例子:

template class C;   // (1) 只有声明

C* p=0;                             // (2) 没问题,不要 C 的定义

template

class C{

public:

        void f();                    // (3) 成员声明

};                                      // (4) class template定义完备

void g (C& c)          //(5) 只用到class template的声明

{

        c.f();                     //(6) 用到了class template的定义:需要C::f()的完整定义

}

在(1)处,编译器只能见到template的声明,见不到其定义(这种声明又称为前置声明,forward declaration)。和常规classes的规则一样,不需要class template的定义,我们就可以定义给类型的指针pointer或引用reference,如这里的(2)。例如函数g()的参数类型C&并不需要template C的完整定义。然而一旦编译器需要知道某个template特化体的大小或程序代码中取用了该特化体的某个成员,编译器就必须见到template的定义。这说明为什么在(6)处,class template的定义必须可见:如果见不到这个定义,编译器就无法确认这个成员是否存在,或程序代码是否有权取用它(必须不为private或protected,才能被取用)。

这里有另外一个表达式,需要class template实例化,因为此处编译器必须知道C的大小。

C* p = new C;

这里必须完成实例化,这么一来编译器才知道C的大小。你可能会注意到无论把template C的参数T以什么样的类型X替换,其template实例化的大小都不会受到影响:任何情况下C都是个empty class。编译器也需要以实例化过程来得知C是否一个可被取用的default构造函数,并确保C没有定义private operator new 和 private operator delete。

有时候,从程序代码本身并不能看出某个class template的成员会被取用。例如C++的重载解析机制overload resolution便需要得知各候选参数的函数额class types:

template

class C {

public:

        C(int);

};

void candidate(C const&);  //(1)

void candiate(int) {}                           //(2)

int main()

{

        candidate(42);    //上面声明的两个函数都可被调用

}

编译器会将candidate(42)解析resolve为(2)的声明。然而(1)处的声明也可能被实例化,用来确定它是否也是上述调用的一个合法候选函数(本例之中实例化可能发生),因为42可隐寓通过单自变量构造函数转型为C类型的 rvalue。

2.缓式实例化Lazy instantiation

3.C++实例化模型Instantiation Model

4.实现方案Implementation Schemes

5.显式实例化Explicit Instantiation

6.小结

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1008505.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号