cpp-expert/template-instantiation:模板实例化机制演示
本目录收录 languages/cpp/expert/template-instantiation.md 的完整可运行代码与实测数据。
要回答的问题:编译器到底为模板生成了几份代码?为什么有的成员函数"消失了"?实例化的符号长什么样?
| 文件 | 说明 |
|---|---|
main.cpp | 演示源码:1 个函数模板 + 1 个类模板,覆盖 4 个类型实参 |
Makefile | make 构建;make symbols 看实例化符号;make size 看体积;make ftime 看编译耗时 |
run-remote.sh | 服务器一键实测脚本(产出本文全部数据) |
编译与运行
bash
make # g++ -O0 -g -Wall -Wextra -std=c++11(旧编译器也可跑,行为与标准版本无关)
make symbols # nm -C 过滤 add/Box,观察实例化产物
make size # 对比 -O0 / -O2 / -O2 -s 的体积
make ftime # -ftime-report 观察实例化耗时与内存占比实测输出(Linux, g++ 4.8.5, -std=c++11)
实例化符号(nm -C 过滤 add/Box)
0000000000400f48 W double add<double>(double, double)
0000000000400fa5 W float add<float>(float, float)
0000000000400f34 W int add<int>(int, int)
0000000000400f74 W std::string add<std::string>(std::string, std::string)
0000000000400fd0 W Box<int>::Box(int)
0000000000400fd0 W Box<int>::Box(int)
0000000000400ff6 W Box<std::string>::Box(std::string)
0000000000400ff6 W Box<std::string>::Box(std::string)
0000000000400f1a W Box<std::string>::~Box()
0000000000400f1a W Box<std::string>::~Box()
0000000000400fe6 W Box<int>::get() const
000000000040101c W Box<std::string>::get() const要点:add 为 4 个类型各生成一份(W = weak 符号,可跨 TU 合并);Box<T>::unused() 没有符号——从未被调用,编译器根本没实例化它。
原始 mangled 符号(nm 不过滤)
0000000000400f48 W _Z3addIdET_S0_S0_
0000000000400fa5 W _Z3addIfET_S0_S0_
0000000000400f34 W _Z3addIiET_S0_S0_
0000000000400f74 W _Z3addISsET_S0_S0_
0000000000400fd0 W _ZN3BoxIiEC1Ei
0000000000400fd0 W _ZN3BoxIiEC2Ei
0000000000400ff6 W _ZN3BoxISsEC1ESs
0000000000400ff6 W _ZN3BoxISsEC2ESs
0000000000400f1a W _ZN3BoxISsED1Ev
0000000000400f1a W _ZN3BoxISsED2Ev
0000000000400fe6 W _ZNK3BoxIiE3getEv二进制体积对比
== -O0 ==
text data bss dec hex filename
4763 724 280 5767 1687 template_instantiation
== -O2 ==
text data bss dec hex filename
3386 700 280 4366 110e /tmp/tmpl_O2
== -O2 -s (strip) ==
text data bss dec hex filename
3386 700 280 4366 110e /tmp/tmpl_O2s文件实际大小:-O0 -g 50112 B;-O2 -g 55736 B;-O2 -s 10512 B(strip 只删符号表与调试段,text 段不变)。
编译耗时(-ftime-report)
template instantiation : 0.02 (15%) usr 0.00 ( 0%) sys 0.07 (28%) wall 6091 kB (19%) ggc
TOTAL : 0.13 0.11 0.25 31332 kB小例子而已,实例化已占编译墙钟 28%、内存 19%——真实项目里模板越多,这个比例越夸张。
运行输出
3
4
ab
6
7
hi