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 W _Z8nonsenseIcEiv
00000000 W _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类型。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架