9.7.1 自动的实例化器(2)
3.两种自动实例化器效率之比较
典型的链接期实例化器只会在一个位置(即repository,储存库)产生模板特化后的代码,而前面的编译期实例化器是在每个直接或者间接使用特化的翻译单元都产生这些代码。因此,与编译期实例化器相比,链接期实例化器的输出占用空间更少。
一个幼稚的分析可能会得到这样的结论:链接期实例化器要比编译期实例化器快。实际上,与编译期实例化相比,在链接期实例化可能更快、可能是一样快,也可能更慢。考虑下面的代码:
- main.c:
- #include<Hashtable.h>
- #include<Hashtable.c> //用于编译期instantiator
- int main() {
- Hashtable<int> table;
- table.insert(7);
- return 0;
- }
让我们假设函数Hashtable<int>::Hashtable()和函数Hashtable<int>::insert(const int&)并没有使用任何其他的模板特化。如果我们使用编译期实例化器来创建这个程序,那么这两个函数的定义将会在main.c的目标代码生成中;当这个目标代码被链接时,所有需要的特化都已经给出了,因此也就没有任何重复的定义需要识别和删除了。
现在假设我们使用链接期实例化器来创建这个程序。当main.c被编译的时候,并不会生成任何特化;当链接main.c的目标代码时,链接期实例化器就需要创建Hashtable<int>::Hashtable()的定义和Hashtable<T>::insert(const int&)的定义,为此,这个实例化器可能创建一个如下的文件:
- Hashtable_int.C:
- #include<Hashtable.h>
- #include<Hashtable.c>
- #pragma instantiate Hashtable<int>::Hashtable()
- #pragma instantiate Hashtable<int>::insert(const int&)
完成了这个文件之后,链接期实例化器就会调用编译器编译这个文件。当编译器返回时,这个实例化器再把编译后的文件添加到需要链接的程序中去。
当我们使用编译期实例化器创建这个程序时,Hashtable.h和Hashtable.c的代码只会被编译一次-发生在mani.c被编译的时候;而当我们使用链接期实例化器来创建这个程序时,Hashtable.c和Hashtable.c的内容都被编译了两次-也是发生在main.c被编译的时候。因此,对于这个程序,链接期实例化器就可能要比编译期实例化器慢;对于一个大的程序,链接期实例化器可能会在不断编译头文件上面花费很多时间。
模板实例化的效率-无论是使用链接期实饲化器还是使用编译期实例化器-至今仍然是C++(www.cppentry.com)用户关心的焦点。在4.2.2节和4.2.3节里,我们给出了程序库用户提高模板实例化效率的一些技术。