Oracle® Developer Studio 12.5:C++ 用户指南

退出打印视图

更新时间: 2016 年 7 月
 
 

7.3 外部实例

对于外部实例方法,所有实例都放置在模板系统信息库中。编译器确保只有一个一致的模板实例存在;这些实例既不是未定义的也不是多重定义的。模板仅在需要时才重新实例化。对于非调试代码,所有对象文件(包括模板缓存中的任何对象文件)在使用 -instances=extern 时的大小总量小于在使用 -instances=global 时的大小总量。

模板实例接受系统信息库中的全局链接。实例是使用外部链接从当前编译单元引用的。


注 - 如果在不同的步骤中进行编译和链接,并且在编译步骤中指定了 -instance=extern,则还必须在链接步骤中指定该选项。

这种方法的缺点是每当您更改程序或进行重大程序更改时都必须清除高速缓存。高速缓存是并行编译的瓶颈,这与使用 dmake 时一样,因为每次只能有一个编译访问高速缓存。另外,您只能在每个目录内生成一个程序。

与在主对象文件中直接创建有效模板实例并在以后丢弃该实例(如果需要)相比,确定某个有效实例是否已在高速缓存中可能需要更长的时间。

使用 –instances=extern 选项指定外部链接。

因为实例存储在模板系统信息库中,所以必须使用 CC 命令将使用外部实例的 C++ 对象链接到程序中。

如果要创建包含了使用的所有模板实例的库,请使用 -xar 选项进行编译。要使用 ar 命令。例如:

example% CC -xar -instances=extern -o libmain.a a.o b.o c.o

7.3.1 可能的高速缓存冲突

如果指定了 -instance=extern,请勿在同一目录中运行不同的编译器版本,以避免可能的高速缓存冲突。使用 -instances=extern 模板模型进行编译时,请注意以下事项:

  • 请勿在同一目录中创建不相关的二进制文件。在同一目录中创建的所有二进制文件(.o.a.so、可执行程序)都应该相关,因为两个或两个以上对象文件通用的所有对象、函数和类型的名称都具有相同的定义。

  • 在同一目录中同时运行多个编译是安全的,例如使用 dmake 时。与另外一个链接步骤同时运行任何编译或链接步骤是不安全的。链接步骤是指用于创建库或可执行程序的任何操作。确保 makefile 中的依赖性不允许任何命令与链接步骤以并行方式运行。

7.3.2 静态实例


注 - -instances=static 选项已过时,因为 -instances=global 现在提供了 static 的所有优点,并克服了其缺点。早期的编译器中提供了此选项来克服现已不存在的问题。

对于静态实例方法,所有实例都被放置在当前编译单元内。因此,模板在每个重新编译期间重新实例化;这些实例不保存到模板系统信息库。

这种方法的缺点是不遵循语言语义,并且会生成很大的对象和可执行文件。

实例接收静态链接。这些实例在当前编译单元外部是不可视的或不可用的。因此,模板可以在多个对象文件中具有相同的实例化。因为多重实例产生了不必要的大程序,所以对于不可能多重实例化模板的小程序可以使用静态实例链接。

静态实例的编译速度很快,因此这种方法也适用于修复并继续方式的调试。(请参见《使用 dbx 调试程序》。)


注 - 如果您的程序取决于多个编译单元间的共享模板实例(例如模板类或模板函数的静态数据成员),请勿使用静态实例方法。否则程序会工作不正常。

可使用 -instances=static 编译器选项指定静态实例链接。

7.3.3 全局实例

与早期的编译器发行版不同,现在不必预防出现一个全局实例有多个副本的情况。

这种方法的优点是通常由其他编译器接受的不正确源代码也能在这种模式中接受。需要特别指出的是,从模板实例内对静态变量的引用是不合法的,但通常是可以接受的。

这种方法的缺点是单个对象文件可能会较大,因为可能会在多个文件中存在模板实例的多个副本。如果编译对象文件以便进行调试时,有些使用了 -g 选项,而有些没有使用该选项,则很难预测是获得链接到程序中模板实例的调试版本还是非调试版本。

模板实例接收全局链接。这些实例在当前编译单元外部是可视的和可用的。

可使用 -instances=global 选项(缺省值)指定全局实例。

7.3.4 显式实例

在显式实例方法中,仅为显式实例化的模板生成实例。隐式实例化不能满足该要求。实例被放置在当前编译单元内。

这种方法的优点是拥有最少的模板编译和最小的对象大小。

缺点是您必须手动执行所有的实例化。

模板实例接收全局链接。这些实例在当前编译单元外部是可视的和可用的。链接程序识别并丢弃重复项目。

可使用 -instances=explicit 选项指定显式实例。

7.3.5 半显式实例

使用半显式实例方法时,仅为显式实例化或模板体内隐式实例化的模板生成实例。显式创建的实例所必需的实例将自动生成。主线代码中隐式实例化不满足该要求。实例被放置在当前编译单元内。因此,模板在每个重新编译期间重新实例化;生成的实例接收全局链接,且不会被保存到模板系统信息库中。

可使用 -instances=semiexplicit 选项指定半显式实例。