首页
社区
课程
招聘
[求助]C++函数返回值是引用的疑问。请教
发表于: 2008-9-12 22:27 5969

[求助]C++函数返回值是引用的疑问。请教

2008-9-12 22:27
5969
int inc1(int& a,int b)
{
  a=a+b;
  return a;
}

int& inc2(int& a,int b)
{
  a=a+b;
  return a;
}

c=inc1(1,2);
如果函数类型是int的话那么在return a 的时候回开辟一个临时变量把a复制过去返回,然后把临时变量的值复制给C是这样的一个过程
而c=inc2(1,2);是不是在返回之前是不是有这样隐含的int& =a语句?

如果不是的话c=inc2(1,2);这个在返回的时候内存是怎么操作的?

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 229
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
int& inc2(int& a,int b)
这个就是返回自己本身,没有经过拷贝,这样理解对否?
2008-9-12 22:42
0
雪    币: 293
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
先贴代码再分析好了,VC2005 Release, 禁用优化,OllyDBG分析。

#include <stdio.h>

int inc0(int a, int b)
{
	a = a + b;
	return a;
}

int inc1(int& a, int b)
{
	a = a + b;
	return a;
}

int& inc2(int& a, int b)
{
	a = a + b;
	return a;
}

int inc3(int* a, int b)
{
	*a = *a + b;
	return *a;
}

int* inc4(int* a, int b)
{
	*a = *a + b;
	return a;
}

int main()
{
	int a = 1;

	inc0(a, 2);
	inc1(a, 2);
	inc2(a, 2);
	inc3(&a, 2);
	inc4(&a, 2);

	return 0;
}


004017D0  /$  55            push    ebp
004017D1  |.  8BEC          mov     ebp, esp
004017D3  |.  51            push    ecx
004017D4  |.  C745 FC 01000>mov     dword ptr [ebp-4], 1
004017DB  |.  6A 02         push    2                         ; /Arg2 = 00000002
004017DD  |.  8B45 FC       mov     eax, dword ptr [ebp-4]    ; |
004017E0  |.  50            push    eax                       ; |Arg1
004017E1  |.  E8 CAFFFFFF   call    004017B0                  ; \Test01.004017B0
004017E6  |.  83C4 08       add     esp, 8
004017E9  |.  6A 02         push    2                         ; /Arg2 = 00000002
004017EB  |.  8D4D FC       lea     ecx, dword ptr [ebp-4]    ; |
004017EE  |.  51            push    ecx                       ; |Arg1
004017EF  |.  E8 9CFFFFFF   call    00401790                  ; \Test01.00401790
004017F4  |.  83C4 08       add     esp, 8
004017F7  |.  6A 02         push    2                         ; /Arg2 = 00000002
004017F9  |.  8D55 FC       lea     edx, dword ptr [ebp-4]    ; |
004017FC  |.  52            push    edx                       ; |Arg1
004017FD  |.  E8 6EFFFFFF   call    00401770                  ; \Test01.00401770
00401802  |.  83C4 08       add     esp, 8
00401805  |.  6A 02         push    2                         ; /Arg2 = 00000002
00401807  |.  8D45 FC       lea     eax, dword ptr [ebp-4]    ; |
0040180A  |.  50            push    eax                       ; |Arg1
0040180B  |.  E8 40FFFFFF   call    00401750                  ; \Test01.00401750
00401810  |.  83C4 08       add     esp, 8
00401813  |.  6A 02         push    2                         ; /Arg2 = 00000002
00401815  |.  8D4D FC       lea     ecx, dword ptr [ebp-4]    ; |
00401818  |.  51            push    ecx                       ; |Arg1
00401819  |.  E8 12FFFFFF   call    00401730                  ; \Test01.00401730
0040181E  |.  83C4 08       add     esp, 8
00401821  |.  33C0          xor     eax, eax
00401823  |.  8BE5          mov     esp, ebp
00401825  |.  5D            pop     ebp
00401826  \.  C3            retn

004017B0  /$  55            push    ebp                       ;  int inc0(int a, int b)
004017B1  |.  8BEC          mov     ebp, esp
004017B3  |.  8B45 08       mov     eax, dword ptr [ebp+8]
004017B6  |.  0345 0C       add     eax, dword ptr [ebp+C]
004017B9  |.  8945 08       mov     dword ptr [ebp+8], eax
004017BC  |.  8B45 08       mov     eax, dword ptr [ebp+8]
004017BF  |.  5D            pop     ebp
004017C0  \.  C3            retn

00401790  /$  55            push    ebp                       ;  int inc1(int& a, int b)
00401791  |.  8BEC          mov     ebp, esp
00401793  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401796  |.  8B08          mov     ecx, dword ptr [eax]
00401798  |.  034D 0C       add     ecx, dword ptr [ebp+C]
0040179B  |.  8B55 08       mov     edx, dword ptr [ebp+8]
0040179E  |.  890A          mov     dword ptr [edx], ecx
004017A0  |.  8B45 08       mov     eax, dword ptr [ebp+8]
004017A3  |.  8B00          mov     eax, dword ptr [eax]
004017A5  |.  5D            pop     ebp
004017A6  \.  C3            retn

00401770  /$  55            push    ebp                       ;  int& inc2(int& a, int b)
00401771  |.  8BEC          mov     ebp, esp
00401773  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401776  |.  8B08          mov     ecx, dword ptr [eax]
00401778  |.  034D 0C       add     ecx, dword ptr [ebp+C]
0040177B  |.  8B55 08       mov     edx, dword ptr [ebp+8]
0040177E  |.  890A          mov     dword ptr [edx], ecx
00401780  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401783  |.  5D            pop     ebp
00401784  \.  C3            retn

00401750  /$  55            push    ebp                       ;  int inc3(int* a, int b)
00401751  |.  8BEC          mov     ebp, esp
00401753  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401756  |.  8B08          mov     ecx, dword ptr [eax]
00401758  |.  034D 0C       add     ecx, dword ptr [ebp+C]
0040175B  |.  8B55 08       mov     edx, dword ptr [ebp+8]
0040175E  |.  890A          mov     dword ptr [edx], ecx
00401760  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401763  |.  8B00          mov     eax, dword ptr [eax]
00401765  |.  5D            pop     ebp
00401766  \.  C3            retn

00401730  /$  55            push    ebp                       ;  int* inc4(int* a, int b)
00401731  |.  8BEC          mov     ebp, esp
00401733  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401736  |.  8B08          mov     ecx, dword ptr [eax]
00401738  |.  034D 0C       add     ecx, dword ptr [ebp+C]
0040173B  |.  8B55 08       mov     edx, dword ptr [ebp+8]
0040173E  |.  890A          mov     dword ptr [edx], ecx
00401740  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401743  |.  5D            pop     ebp
00401744  \.  C3            retn

从上面可以看出 inc0 传入的是数值,返回的也是数值,函数里面不能改变外面的值。

inc1,2,3,4 传入的都是指针,在函数内可以改变外面的变量的值。inc1 和 inc3 返回的都是数值,inc2 和 inc4 返回的都是指针。inc1 和 inc3 基本上没有区别,inc2 和 inc4 基本上也没有区别。 从高级语言上看(比如C++),&a 和 *a 都可以起到将函数内外的变量联系起来的作用,无论改函数里面还是外面的变量,改的都是同一个地址的值。

&a 的定义方法感觉更直观一些,因为只要函数的参数名字,和传进来变量名字一样,别人阅读程序的时候也很容易理解指的是同一个变量。用起来也很方便,不用像指针那样,还要加*才能取变量的值。

*a 的定义方法随便一本编程书上都会讲,相对来说大家理解更深刻吧。

所以两种定义方法各有个的好处,不过使用的时候,要注意函数是怎么定义的,传递参数的时候配套使用就行了。

还有,inc1(1,2) 这样的写法是不对的。因为根据 inc1 的定义,这里需要传入的是一个变量(从汇编的角度来看这里需要的是一个变量的地址),而这里的 1 和 2 一样都是常数,一定要事先定义变量再传入才可以。 就好像我们能用 i++, 但是不能用 2++, 3++ 一样。

以上纯属个人理解,欢迎指正。
2008-9-13 00:41
0
雪    币: 63
活跃值: (17)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
int& inc2(int& a,int b);
c=inc2(1,2);

新的C++标准还没有出来
引用不能绑定到右值中
2008-9-13 08:12
0
雪    币: 229
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢3楼,提供了一个学习的好方法,不懂原理就自己调试。

再次感谢这份详尽的分析报告
2008-9-13 11:54
0
游客
登录 | 注册 方可回帖
返回
//