C++中的对象返回

本文详细解释了函数中返回值的概念及其实现方式,包括基本类型的返回值如何通过寄存器传递,以及对象类型的返回值如何通过栈帧进行构造和传递。
一 何为返回值
一个函数有返回值类型声明,比如int,char,int*,char*,struct xxxx 等。
在函数执行结束的末尾,需要显示的写代码return xxx与函数声明的返回值类型相同。


二 普通返回值类型
int,char,int*,char*,float* 等。
这种返回值类型都是直接通过eax寄存器返回的,返回值的生命周期,显然就是与eax寄存器的值是否有被覆盖有关。
我们看下具体实例:
int func()
{
printf("func running\n");
return 10;
}


00000000004005a4 <_Z4funcv>:
  4005a4:       55                      push   %rbp
  4005a5:       48 89 e5                mov    %rsp,%rbp
  4005a8:       bf c8 06 40 00          mov    $0x4006c8,%edi
  4005ad:       e8 d6 fe ff ff          callq  400488 <puts@plt>
  4005b2:       b8 0a 00 00 00          mov    $0xa,%eax  ;//return 10
  4005b7:       c9                      leaveq 
  4005b8:       c3                      retq   


三 对象返回类型
对象返回类型和普通返回类型稍有不同,对象返回类型和返回动态申请的对象的地址是类似的,即便返回值是对象本身。
int main()
{
int b = func();
get_str();
return 0;
}


std::string get_str()
{
printf("get_str running\n");
return std::string("get_str");
}


0000000000400830 <main>:
  400830:       55                      push   %rbp
  400831:       48 89 e5                mov    %rsp,%rbp
  400834:       48 83 ec 10             sub    $0x10,%rsp
  400838:       e8 67 ff ff ff          callq  4007a4 <_Z4funcv>
  40083d:       89 45 fc                mov    %eax,-0x4(%rbp);
  400840:       48 8d 45 f0             lea    -0x10(%rbp),%rax//从栈顶开始腾出一块空间,存到rax,转移到rdi传到函数内部
  400844:       48 89 c7                mov    %rax,%rdi
  400847:       e8 6d ff ff ff          callq  4007b9 <_Z7get_strv>


00000000004007b9 <_Z7get_strv>:
  4007b9:       55                      push   %rbp
  4007ba:       48 89 e5                mov    %rsp,%rbp
  4007bd:       41 54                   push   %r12
  4007bf:       53                      push   %rbx
  4007c0:       48 83 ec 10             sub    $0x10,%rsp
  4007c4:       48 89 fb                mov    %rdi,%rbx  ;//取出外面传进来的临时对象地址,进行赋值构造std::string
  4007c7:       bf 65 09 40 00          mov    $0x400965,%edi
  4007cc:       e8 67 fe ff ff          callq  400638 <puts@plt>
  4007d1:       49 89 dc                mov    %rbx,%r12
  4007d4:       48 8d 45 ef             lea    -0x11(%rbp),%rax
  4007d8:       48 89 c7                mov    %rax,%rdi
  4007db:       e8 a8 fe ff ff          callq  400688 <_ZNSaIcEC1Ev@plt>
  4007e0:       48 8d 45 ef             lea    -0x11(%rbp),%rax
  4007e4:       48 89 c2                mov    %rax,%rdx
  4007e7:       be 75 09 40 00          mov    $0x400975,%esi
  4007ec:       4c 89 e7                mov    %r12,%rdi
  4007ef:       e8 74 fe ff ff          callq  400668 <_ZNSsC1EPKcRKSaIcE@plt>
  4007f4:       eb 1f                   jmp    400815 <_Z7get_strv+0x5c>
  4007f6:       89 d3                   mov    %edx,%ebx
  4007f8:       49 89 c4                mov    %rax,%r12
  4007fb:       48 8d 45 ef             lea    -0x11(%rbp),%rax
  4007ff:       48 89 c7                mov    %rax,%rdi
注意:这里调用get_str函数调用之前,main函数先预留一块临时对象空间。sub    $0x10,%rsp;


PS:如果读不懂此篇博客,建议先学习一下什么是栈帧,以及elf文件编译后调用函数的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值