C++中模板生成时机

一、模板
模板是C++中相对比较不太常见的结构,它实现了一些定义按照使用而动态由编译器实现的功能。或者说它部分实现了一些代码动态生成,将程序员的一些工作转移给了编译器来完成。并且它可以使用和内存的使用一样,只有在真正使用到(需要一种模板定义)的时候,此时才真正生成这种模板的一个实例。这一点和各种现代的内存管理系统一样,模板只是声明,它并不真正进行资源的分配(事实上,如果模板不被引用,它也无法知道如何实例化),只有当真正使用到的时候在进行实体声明。
二、在何处生成
模板一般定义于头文件中,例如STL库中的各种基础库模板。然后各个变量引用的时候会进行实例的生成,包括变量、函数、类等的声明。这也就意味着有多少个编译单元使用了一个模板,那么就有多少个编译单元包含了这种类的实例。那么在最终链接的时候是否会出现链接冲突?
[tsecer@Harry template]$ cat tpl.cpp 
template <class basetype>
int nonsense()
{
    return 0;
}
int main()
{
    return nonsense<char>() + nonsense<int>();
}
[tsecer@Harry template]$ g++ -c tpl.cpp 
[tsecer@Harry template]$ nm tpl.o 
00000000 _Z8nonsenseIcEiv
00000000 _Z8nonsenseIiEiv
         U __gxx_personality_v0
00000000 T main
[tsecer@Harry template]$ c++filt _Z8nonsenseIcEiv _Z8nonsenseIiEiv
int nonsense<char>()
int nonsense<int>()
[tsecer@Harry template]$ readelf -a tpl.o
……
    12: 00000000    33 FUNC    GLOBAL DEFAULT    3 main
    13: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __gxx_personality_v0
    14: 00000000    10 FUNC    WEAK   DEFAULT    7 _Z8nonsenseIcEiv
    15: 00000000    10 FUNC    WEAK   DEFAULT    8 _Z8nonsenseIiEiv
也就是模板的实例都是WEAK属性的。之前曾经讨论过每个C++类的虚函数表也是通过WEAK属性实现,所以这里并不是很特别。
三、命名的一些规则
上面可以看到其中对于命令的一些规则还是比较诡异的,但是通过gdb的代码是可以看到其中的变量的部分编码方法,其中的_Z是每个C++mangle之后的变量名,之后的8表示了nonsense字符串的长度。
这一点感觉比较繁琐并且无趣,实现代码位于gdb的gdb-6.0\libiberty\cp-demangle.c文件中,从中可以看到很多的这个变量编码的解析方法。例如其中的模板参数的解析使用
demangle_template_args
函数完成,对应的变量_Z8nonsenseIcEiv中从I开始,接下来的c表示模板的参数为一个char类型,E表示模板参数列表开始,i表示返回值为int类型,v表示参数为void类型。

posted on 2019-03-07 09:18  tsecer  阅读(424)  评论(0编辑  收藏  举报

导航