码迷,mamicode.com
首页 > 编程语言 > 详细

C++编译器函数模版机制剖析 - 函数模版的本质

时间:2015-07-03 10:38:42      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:c++   编译器   函数模版   本质   

思考:为什么函数模板可以和函数重载放在一块。C++编译器是如何提供函数模板机制的?

demo 1

#include <cstdio>
#include <iostream>
using namespace std;

// 1.cpp

// g++ -S 1.cpp  -o 1.s
template <typename T>
void myswap(T &a, T &b)
{
	T c = 0;
	c = a;
	a = b;
	b = c;
	cout << "hello ....我是模板函数 欢迎 calll 我" << endl;
}

int main()
{
	{

		int x = 10; 
		int y = 20;

		myswap<int>(x, y); //1 函数模板 显示类型 调用

		printf("x:%d y:%d \n", x, y);
	}


	{
		char a = 'a'; 
		char b = 'b';

		myswap<char>(a, b); //1 函数模板 显示类型 调用
		printf("a:%c b:%c \n", a, b);
	}
	return 0;
}

把demo 1编译成汇编文件,查看:

	.file	"1.cpp"
.lcomm __ZStL8__ioinit,1,1
	.def	___main;	.scl	2;	.type	32;	.endef
	.section .rdata,"dr"
LC0:
	.ascii "x:%d y:%d \12\0"
LC1:
	.ascii "a:%c b:%c \12\0"
	.def	___gxx_personality_sj0;	.scl	2;	.type	32;	.endef
	.def	__Unwind_SjLj_Register;	.scl	2;	.type	32;	.endef
	.def	__Unwind_SjLj_Unregister;	.scl	2;	.type	32;	.endef
	.text
	.globl	_main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%edi
	pushl	%esi
	pushl	%ebx
	andl	$-16, %esp
	subl	$96, %esp
	movl	$___gxx_personality_sj0, 52(%esp)
	movl	$LLSDA959, 56(%esp)
	leal	60(%esp), %eax
	movl	%ebp, (%eax)
	movl	$L5, %edx
	movl	%edx, 4(%eax)
	movl	%esp, 8(%eax)
	leal	28(%esp), %eax
	movl	%eax, (%esp)
	call	__Unwind_SjLj_Register
	call	___main
	movl	$10, 92(%esp)
	movl	$20, 88(%esp)
	leal	88(%esp), %eax
	movl	%eax, 4(%esp)
	leal	92(%esp), %eax
	movl	%eax, (%esp)
	movl	$1, 32(%esp)
<span style="color:#ff0000;">	call	__Z6myswapIiEvRT_S1_ // 41 call 117</span>
	movl	88(%esp), %edx
	movl	92(%esp), %eax
	movl	%edx, 8(%esp)
	movl	%eax, 4(%esp)
	movl	$LC0, (%esp)
	call	_printf
	movb	$97, 87(%esp)
	movb	$98, 86(%esp)
	leal	86(%esp), %eax
	movl	%eax, 4(%esp)
	leal	87(%esp), %eax
	movl	%eax, (%esp)
	movl	$2, 32(%esp)
<span style="color:#ff0000;">	call	__Z6myswapIcEvRT_S1_ // 55 call 145</span>
	movb	86(%esp), %al
	movsbl	%al, %edx
	movb	87(%esp), %al
	movsbl	%al, %eax
	movl	%edx, 8(%esp)
	movl	%eax, 4(%esp)
	movl	$LC1, (%esp)
	call	_printf
	movl	$0, %eax
	movl	%eax, 24(%esp)
	jmp	L8
L5:
	movl	36(%esp), %edx
	movl	32(%esp), %eax
	testl	%eax, %eax
	je	L6
	cmpl	$1, %eax
	je	L7
		.word	0x0b0f
L6:
	movl	%edx, %eax
	movl	%eax, (%esp)
	movl	$-1, 32(%esp)
	call	__Unwind_SjLj_Resume
L7:
	movl	%edx, %eax
	movl	%eax, (%esp)
	movl	$-1, 32(%esp)
	call	__Unwind_SjLj_Resume
L8:
	leal	28(%esp), %eax
	movl	%eax, (%esp)
	call	__Unwind_SjLj_Unregister
	movl	24(%esp), %eax
	leal	-12(%ebp), %esp
	popl	%ebx
	popl	%esi
	popl	%edi
	popl	%ebp
	ret
	.section	.gcc_except_table,"w"
LLSDA959:
	.byte	0xff
	.byte	0xff
	.byte	0x1
	.uleb128 LLSDACSE959-LLSDACSB959
LLSDACSB959:
	.uleb128 0
	.uleb128 0
	.uleb128 0x1
	.uleb128 0
LLSDACSE959:
	.text
	.section .rdata,"dr"
	.align 4
LC2:
	.ascii "hello ....\316\322\312\307\304\243\260\345\272\257\312\375 \273\266\323\255 calll \316\322\0"
	.section	.text$_Z6myswapIiEvRT_S1_,"x"
	.linkonce discard
	.globl	__Z6myswapIiEvRT_S1_
	.def	__Z6myswapIiEvRT_S1_;	.scl	2;	.type	32;	.endef
<span style="color:#ff0000;">__Z6myswapIiEvRT_S1_: // 117</span>
	pushl	%ebp
	movl	%esp, %ebp
	subl	$40, %esp
	movl	$0, -12(%ebp)
	movl	8(%ebp), %eax
	movl	(%eax), %eax
	movl	%eax, -12(%ebp)
	movl	12(%ebp), %eax
	movl	(%eax), %edx
	movl	8(%ebp), %eax
	movl	%edx, (%eax)
	movl	12(%ebp), %eax
	movl	-12(%ebp), %edx
	movl	%edx, (%eax)
	movl	$LC2, 4(%esp)
	movl	$__ZSt4cout, (%esp)
	call	__ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
	movl	$__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, (%esp)
	movl	%eax, %ecx
	call	__ZNSolsEPFRSoS_E
	subl	$4, %esp
	leave
	ret
	.section	.text$_Z6myswapIcEvRT_S1_,"x"
	.linkonce discard
	.globl	__Z6myswapIcEvRT_S1_
	.def	__Z6myswapIcEvRT_S1_;	.scl	2;	.type	32;	.endef
<span style="color:#ff0000;">__Z6myswapIcEvRT_S1_: // 145</span>
	pushl	%ebp
	movl	%esp, %ebp
	subl	$40, %esp
	movb	$0, -9(%ebp)
	movl	8(%ebp), %eax
	movb	(%eax), %al
	movb	%al, -9(%ebp)
	movl	12(%ebp), %eax
	movb	(%eax), %dl
	movl	8(%ebp), %eax
	movb	%dl, (%eax)
	movl	12(%ebp), %eax
	movb	-9(%ebp), %dl
	movb	%dl, (%eax)
	movl	$LC2, 4(%esp)
	movl	$__ZSt4cout, (%esp)
	call	__ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
	movl	$__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, (%esp)
	movl	%eax, %ecx
	call	__ZNSolsEPFRSoS_E
	subl	$4, %esp
	leave
	ret
	.text
	.def	___tcf_0;	.scl	3;	.type	32;	.endef
___tcf_0:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	movl	$__ZStL8__ioinit, %ecx
	call	__ZNSt8ios_base4InitD1Ev
	leave
	ret
	.def	__Z41__static_initialization_and_destruction_0ii;	.scl	3;	.type	32;	.endef
__Z41__static_initialization_and_destruction_0ii:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	cmpl	$1, 8(%ebp)
	jne	L12
	cmpl	$65535, 12(%ebp)
	jne	L12
	movl	$__ZStL8__ioinit, %ecx
	call	__ZNSt8ios_base4InitC1Ev
	movl	$___tcf_0, (%esp)
	call	_atexit
L12:
	leave
	ret
	.def	__GLOBAL__sub_I_main;	.scl	3;	.type	32;	.endef
__GLOBAL__sub_I_main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	movl	$65535, 4(%esp)
	movl	$1, (%esp)
	call	__Z41__static_initialization_and_destruction_0ii
	leave
	ret
	.section	.ctors,"w"
	.align 4
	.long	__GLOBAL__sub_I_main
	.def	__Unwind_SjLj_Resume;	.scl	2;	.type	32;	.endef
	.def	_printf;	.scl	2;	.type	32;	.endef
	.def	__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_;	.scl	2;	.type	32;	.endef
	.def	__ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc;	.scl	2;	.type	32;	.endef
	.def	__ZNSolsEPFRSoS_E;	.scl	2;	.type	32;	.endef
	.def	__ZNSt8ios_base4InitD1Ev;	.scl	2;	.type	32;	.endef
	.def	__ZNSt8ios_base4InitC1Ev;	.scl	2;	.type	32;	.endef
	.def	_atexit;	.scl	2;	.type	32;	.endef
观察发现一个现象,myswap函数模版有一个声明,两个定义,这种情况和我在“为什么会有函数模版中”博文中提到的两个myswap函数很相似,实际这里体现了C++实现函数模版的本,本来需要程序员根据需要去写很多个逻辑相同,参数不同的函数,但是C++编译器帮我们做了这件事,根据调用会自动生成这些函数,这也是为什么函数模版可以和普通函数放在一起。

总结:函数模版机制结论:

编译器并不是把函数模版处理成能够处理任意类的函数;

编译器从函数模版通过具体类型产生不同的函数;

编译器会对函数模版进行两次编译:在声明的地方对模版代码本身进行编译,在调用的地方对参数替换后的代码进行编译。



版权声明:本文为博主原创文章,未经博主允许不得转载。

C++编译器函数模版机制剖析 - 函数模版的本质

标签:c++   编译器   函数模版   本质   

原文地址:http://blog.csdn.net/zyq522376829/article/details/46737611

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!