来个常规源码
[root@localhost design]# ./a.out
1
[root@localhost design]# cat dd.cpp
#include<iostream>
template <typename T>
void show(T a) {
std::cout << a << std::endl;
}
int main(){
show(1);
}
指令反编译一下
# objdump -d a.out
0000000000400814 <_Z4showIiEvT_>:
400814: 55 push %rbp
400815: 48 89 e5 mov %rsp,%rbp
400818: 48 83 ec 10 sub $0x10,%rsp
40081c: 89 7d fc mov %edi,-0x4(%rbp)
40081f: 8b 45 fc mov -0x4(%rbp),%eax
400822: 89 c6 mov %eax,%esi
400824: bf 60 10 60 00 mov $0x601060,%edi
400829: e8 12 fe ff ff callq 400640 <_ZNSolsEi@plt>
40082e: be b0 06 40 00 mov $0x4006b0,%esi
400833: 48 89 c7 mov %rax,%rdi
400836: e8 65 fe ff ff callq 4006a0 <_ZNSolsEPFRSoS_E@plt>
40083b: c9 leaveq
40083c: c3 retq
40083d: 0f 1f 00 nopl (%rax)
改改代码执行一下
[root@localhost design]# g++ dd.cpp -ldl -rdynamic
[root@localhost design]# ./a.out
1
1
[root@localhost design]# cat dd.cpp
#include<dlfcn.h>
#include<iostream>
template <typename T>
void show(T a) {
std::cout << a << std::endl;
}
int main(){
show(1);
void(*td)(int);
*(void**)&td = dlsym(RTLD_DEFAULT,"_Z4showIiEvT_");
td(1);
}
最后成功用C代码调用类模板类。
模板类使用类才会生成代码。不适用这个模板就毫无意义,也就是实例化。
上面的C
调用如果没有show(1)
是执行不起来的。
模板在编译的时候会以上下文作为依据生成一个全局唯一函数,包括模板类也是这样。这就和C
的ABI
有点类似了。
总结就是,模板函数只是被编译器编译成了另类的函数而已。没什么大不了的。而模板类则是被编译器改成了另类的类,使用的时候才创建对应类的代码,这个类是新的类型哟。
多个实例就有多份代码,怎么去重?编译器负责去重。特别是大型项目中的不同的.o
里面。
下面反过来用C
实现一下模板
[root@localhost design]# g++ dd.cpp -std=c++11
[root@localhost design]# ./a.out
1
[root@localhost design]# cat dd.cpp
#include<iostream>
template <typename T>
void show(T a);
extern "C" void _Z4showIiEvT_(int a) {
std::cout << a << std::endl;
}
int main(){
show(1);
}