当前位置: 首页 > news >正文

网站制作推广方案做外包网站的公司是怎样的

网站制作推广方案,做外包网站的公司是怎样的,拼多多网店代运营要多少费用,湖北省建设交易协会网站author: hjjdebug date: 2025年 06月 04日 星期三 11:19:42 CST descrip: c返回对象,返回引用,返回指针有什么区别? 文章目录 1. 测试代码:2. 反汇编代码分析2.1: 调用代码分析2.2: 被调用函数代码分析, 看看它们是怎样返回eax的. 3. 结论: 返回指针,就是返回一个地…

author: hjjdebug
date: 2025年 06月 04日 星期三 11:19:42 CST
descrip: c++返回对象,返回引用,返回指针有什么区别?


文章目录

  • 1. 测试代码:
  • 2. 反汇编代码分析
    • 2.1: 调用代码分析
    • 2.2: 被调用函数代码分析, 看看它们是怎样返回eax的.
  • 3. 结论:

返回指针,就是返回一个地址,这个容易理解.
返回对象和返回引用呢? 一般来讲,也是返回一个地址, 你想,返回值就存储在eax中,
它在64位机器上也就存储64bits数据, 也就只能存储一个地址.
除非你的对象占据的内存不大于64bits, 例如只有一个int,或者其它由bit组成的位,
能直接返回对象,大于64bits 的对象, 返回对象或者返回引用,就是返回的对象地址.
实测的才最有说服力. 看看它的具体实现细节.

1. 测试代码:

$ cat main.cpp#include <stdio.h>
class MyClass
{
public:int i1;int i2;float f;char *p;
public:MyClass(){i1=i2=0;f=0.0;p=NULL;}
};
MyClass getObj1()
{MyClass obj;obj.i1=1;return obj;
}MyClass& getObj2()
{static MyClass obj; obj.i1=2;
// warning: reference to local variable ‘obj’ returned [-Wreturn-local-addr]
// 所以我需要吧 obj 声明为static, 这样就没有warning 了return obj; }MyClass *getObj3()
{static MyClass obj;obj.i1=3;
// warning: address of local variable ‘obj’ returned [-Wreturn-local-addr] 
// 所以我需要吧 obj 声明为static, 这样就没有warning 了return &obj; 
}int main() {MyClass obj1=getObj1();MyClass obj2=getObj2();MyClass *obj3=getObj3();printf("obj1:%d,obj2:%d,obj3:%d\n",obj1.i1,obj2.i1,obj3->i1);return 0;
}

执行结果:
$ ./tt
obj1:1,obj2:2,obj3:3

2. 反汇编代码分析

2.1: 调用代码分析

	MyClass obj1=getObj1();4012b1:	48 8d 45 c0          	lea    -0x40(%rbp),%rax     # 直接传递的obj1的地址,做为this指针,显然调用被优化了.4012b5:	48 89 c7             	mov    %rax,%rdi4012b8:	e8 d9 fe ff ff       	callq  401196 <getObj1()>MyClass obj2=getObj2();4012bd:	e8 24 ff ff ff       	callq  4011e6 <getObj2()>4012c2:	48 89 c1             	mov    %rax,%rcx           # 返回值送rcx4012c5:	48 8b 01             	mov    (%rcx),%rax         # 解引用i1送rax4012c8:	48 8b 51 08          	mov    0x8(%rcx),%rdx      # 解引用i2送rdx4012cc:	48 89 45 e0          	mov    %rax,-0x20(%rbp)    # 保留i14012d0:	48 89 55 e8          	mov    %rdx,-0x18(%rbp)    # 保留i24012d4:	48 8b 41 10          	mov    0x10(%rcx),%rax     # 解引用f送rax4012d8:	48 89 45 f0          	mov    %rax,-0x10(%rbp)    # 保留fMyClass *obj3=getObj3();4012dc:	e8 5d ff ff ff       	callq  40123e <getObj3()>4012e1:	48 89 45 b8          	mov    %rax,-0x48(%rbp)    # 保留返回值到obj3printf("obj1:%d,obj2:%d,obj3:%d\n",obj1.i1,obj2.i1,obj3->i1);4012e5:	48 8b 45 b8          	mov    -0x48(%rbp),%rax4012e9:	8b 08                	mov    (%rax),%ecx        # obj3->i1 送ecx,4参数4012eb:	8b 55 e0             	mov    -0x20(%rbp),%edx   # obj2.i1 送edx,3参数4012ee:	8b 45 c0             	mov    -0x40(%rbp),%eax   # obj1.i1 送esi,2参数4012f1:	89 c6                	mov    %eax,%esi4012f3:	48 8d 3d 0a 0d 00 00 	lea    0xd0a(%rip),%rdi        # 402004 字符串送rdi,1参数4012fa:	b8 00 00 00 00       	mov    $0x0,%eax4012ff:	e8 6c fd ff ff       	callq  401070 <printf@plt>      #调用printfreturn 0;401304:	b8 00 00 00 00       	mov    $0x0,%eax
}

可见返回对象的赋值操作被优化没了,直接传递了目标地址.
返回引用还可以看到对目标对象的赋值操作.

2.2: 被调用函数代码分析, 看看它们是怎样返回eax的.

MyClass getObj1()
{401196:	f3 0f 1e fa          	endbr64 40119a:	55                   	push   %rbp40119b:	48 89 e5             	mov    %rsp,%rbp40119e:	48 83 ec 20          	sub    $0x20,%rsp4011a2:	48 89 7d e8          	mov    %rdi,-0x18(%rbp)  # 保存this指针4011a6:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax4011ad:	00 00 4011af:	48 89 45 f8          	mov    %rax,-0x8(%rbp)  # 堆栈安全测试代码4011b3:	31 c0                	xor    %eax,%eaxMyClass obj;4011b5:	48 8b 45 e8          	mov    -0x18(%rbp),%rax  #传来的this指针做对象指针来构建对象4011b9:	48 89 c7             	mov    %rax,%rdi4011bc:	e8 5f 01 00 00       	callq  401320 <MyClass::MyClass()> #调用类的构造函数obj.i1=1;4011c1:	48 8b 45 e8          	mov    -0x18(%rbp),%rax  # 把1赋值给对象的i14011c5:	c7 00 01 00 00 00    	movl   $0x1,(%rax)return obj;4011cb:	90                   	nop
}4011cc:	48 8b 45 f8          	mov    -0x8(%rbp),%rax4011d0:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax     #测试堆栈是否被破坏4011d7:	00 00 4011d9:	74 05                	je     4011e0 <getObj1()+0x4a> #堆栈正常则正常返回4011db:	e8 b0 fe ff ff       	callq  401090 <__stack_chk_fail@plt> #调用堆栈被破坏代码4011e0:	48 8b 45 e8          	mov    -0x18(%rbp),%rax  #正常返回,this指针返回(赋值给eax)4011e4:	c9                   	leaveq 4011e5:	c3                   	retq   MyClass& getObj2()
{4011e6:	f3 0f 1e fa          	endbr64 4011ea:	55                   	push   %rbp4011eb:	48 89 e5             	mov    %rsp,%rbpstatic MyClass obj; 4011ee:	0f b6 05 83 2e 00 00 	movzbl 0x2e83(%rip),%eax        # 404078 <guard variable for getObj2()::obj>4011f5:	84 c0                	test   %al,%al4011f7:	0f 94 c0             	sete   %al                     # 根据ZF标志位的状态设置al寄存器,如果ZF=1,则al=14011fa:	84 c0                	test   %al,%al4011fc:	74 2d                	je     40122b <getObj2()+0x45> # 保护位为0则跳转4011fe:	48 8d 3d 73 2e 00 00 	lea    0x2e73(%rip),%rdi        # 404078 <guard variable for getObj2()::obj>401205:	e8 96 fe ff ff       	callq  4010a0 <__cxa_guard_acquire@plt>40120a:	85 c0                	test   %eax,%eax40120c:	0f 95 c0             	setne  %al         # ZF不等于1,设置al=140120f:	84 c0                	test   %al,%al401211:	74 18                	je     40122b <getObj2()+0x45>401213:	48 8d 3d 46 2e 00 00 	lea    0x2e46(%rip),%rdi        # 404060 <getObj2()::obj>, 对象指针40121a:	e8 01 01 00 00       	callq  401320 <MyClass::MyClass()>  # 调用构造函数40121f:	48 8d 3d 52 2e 00 00 	lea    0x2e52(%rip),%rdi        # 404078 <guard variable for getObj2()::obj>401226:	e8 55 fe ff ff       	callq  401080 <__cxa_guard_release@plt> # 调用 guard_releaseobj.i1=2;40122b:	c7 05 2b 2e 00 00 02 	movl   $0x2,0x2e2b(%rip)        # 404060 <getObj2()::obj>2送给i1401232:	00 00 00 
// warning: reference to local variable ‘obj’ returned [-Wreturn-local-addr]
// 所以我需要吧 obj 声明为static, 这样就没有warning 了return obj; 401235:	48 8d 05 24 2e 00 00 	lea    0x2e24(%rip),%rax        # 404060 <getObj2()::obj>  返回对象地址}40123c:	5d                   	pop    %rbp40123d:	c3                   	retq   在 404060 内存区构建了静态变量obj, 调用了构造函数,并将i1赋值为2, 返回对象地址
404078是哨兵保护字节.
0x404000-0x405000都属于可读可写区,包括.got.plt, .data, 及其它例如声明的静态变量.
其后面的可读可写区就是堆了.000000000040123e <getObj3()>:MyClass *getObj3()
{40123e:	f3 0f 1e fa          	endbr64 401242:	55                   	push   %rbp401243:	48 89 e5             	mov    %rsp,%rbpstatic MyClass obj;401246:	0f b6 05 4b 2e 00 00 	movzbl 0x2e4b(%rip),%eax        # 404098 <guard variable for getObj3()::obj>40124d:	84 c0                	test   %al,%al40124f:	0f 94 c0             	sete   %al401252:	84 c0                	test   %al,%al401254:	74 2d                	je     401283 <getObj3()+0x45>401256:	48 8d 3d 3b 2e 00 00 	lea    0x2e3b(%rip),%rdi        # 404098 <guard variable for getObj3()::obj>40125d:	e8 3e fe ff ff       	callq  4010a0 <__cxa_guard_acquire@plt> # 我跟踪了一下,这些代码是会走到的,401262:	85 c0                	test   %eax,%eax401264:	0f 95 c0             	setne  %al401267:	84 c0                	test   %al,%al401269:	74 18                	je     401283 <getObj3()+0x45>40126b:	48 8d 3d 0e 2e 00 00 	lea    0x2e0e(%rip),%rdi        # 404080 <getObj3()::obj>401272:	e8 a9 00 00 00       	callq  401320 <MyClass::MyClass()>401277:	48 8d 3d 1a 2e 00 00 	lea    0x2e1a(%rip),%rdi        # 404098 <guard variable for getObj3()::obj>40127e:	e8 fd fd ff ff       	callq  401080 <__cxa_guard_release@plt>obj.i1=3;401283:	c7 05 f3 2d 00 00 03 	movl   $0x3,0x2df3(%rip)        # 404080 <getObj3()::obj>40128a:	00 00 00 
// warning: address of local variable ‘obj’ returned [-Wreturn-local-addr] 
// 所以我需要吧 obj 声明为static, 这样就没有warning 了return &obj; 40128d:	48 8d 05 ec 2d 00 00 	lea    0x2dec(%rip),%rax        # 404080 <getObj3()::obj>
}401294:	5d                   	pop    %rbp401295:	c3                   	retq   与返回引用极其相似,从实现来看,你是分辨不出返回的到底是指针还是引用的, 返回值的解释由调用者去解释.404080 内存区构建了静态变量obj, 调用了构造函数,并将i1赋值为3, 返回对象地址
404098是哨兵保护字节.
我跟踪了一下,哨兵代码是会走到的,即执行流程是获取哨兵,执行构造,释放哨兵. 哨兵应该是检查数据区是否被破坏的保护检测.

我忽然想知道, 返回对象的函数getObj1() 如果也是一个static obj 会如何?
我研究了一下, 调用没有变化, 仍然传递了this指针.
但getObj1() 的实现有了一点变化, 因为要构建static obj, 然后把static_obj 向this指针copy

MyClass getObj1()
{401196:	f3 0f 1e fa          	endbr64 40119a:	55                   	push   %rbp40119b:	48 89 e5             	mov    %rsp,%rbp40119e:	48 83 ec 10          	sub    $0x10,%rsp4011a2:	48 89 7d f8          	mov    %rdi,-0x8(%rbp)       #保留this 指针static MyClass obj;4011a6:	0f b6 05 cb 2e 00 00 	movzbl 0x2ecb(%rip),%eax        # 404078 <guard variable for getObj1()::obj>4011ad:	84 c0                	test   %al,%al4011af:	0f 94 c0             	sete   %al4011b2:	84 c0                	test   %al,%al4011b4:	74 2d                	je     4011e3 <getObj1()+0x4d>4011b6:	48 8d 3d bb 2e 00 00 	lea    0x2ebb(%rip),%rdi        # 404078 <guard variable for getObj1()::obj>4011bd:	e8 de fe ff ff       	callq  4010a0 <__cxa_guard_acquire@plt>4011c2:	85 c0                	test   %eax,%eax4011c4:	0f 95 c0             	setne  %al4011c7:	84 c0                	test   %al,%al4011c9:	74 18                	je     4011e3 <getObj1()+0x4d>4011cb:	48 8d 3d 8e 2e 00 00 	lea    0x2e8e(%rip),%rdi        # 404060 <getObj1()::obj>4011d2:	e8 79 01 00 00       	callq  401350 <MyClass::MyClass()>4011d7:	48 8d 3d 9a 2e 00 00 	lea    0x2e9a(%rip),%rdi        # 404078 <guard variable for getObj1()::obj>4011de:	e8 9d fe ff ff       	callq  401080 <__cxa_guard_release@plt>obj.i1=1;4011e3:	c7 05 73 2e 00 00 01 	movl   $0x1,0x2e73(%rip)        # 404060 <getObj1()::obj>4011ea:	00 00 00 return obj;     # 对象成员obj向this copy 的过程.4011ed:	48 8b 4d f8          	mov    -0x8(%rbp),%rcx4011f1:	48 8b 05 68 2e 00 00 	mov    0x2e68(%rip),%rax        # 404060 <getObj1()::obj>4011f8:	48 8b 15 69 2e 00 00 	mov    0x2e69(%rip),%rdx        # 404068 <getObj1()::obj+0x8>4011ff:	48 89 01             	mov    %rax,(%rcx)401202:	48 89 51 08          	mov    %rdx,0x8(%rcx)401206:	48 8b 05 63 2e 00 00 	mov    0x2e63(%rip),%rax        # 404070 <getObj1()::obj+0x10>40120d:	48 89 41 10          	mov    %rax,0x10(%rcx)
}401211:	48 8b 45 f8          	mov    -0x8(%rbp),%rax          # 返回this 指针401215:	c9                   	leaveq 401216:	c3                   	retq  

3. 结论:

返回对象, 优化了赋值构造,直接传递了this指针. 在函数内部有外部对象向this对象copy的过程.
返回引用. 在函数内部没有copy的过程, 但在调用处,有赋值构造的过程.
返回指针. 就是返回一个地址, 对象的使用由指针访问.
返回对象,或返回引用都是返回一个地址, 返回对象返回的是目标地址,返回引用返回的是源地址,它们都伴随有源对象向目标对象的数据copy,只是发生的时机不同.
而指针没有目标之说,它指的就是源对象的地址.

http://www.dtcms.com/a/576547.html

相关文章:

  • 网站 语言选择山西省网站
  • 免费企业网站建设单位wordpress调用当前子分类
  • 如何做阅读网站婚纱摄影网站的设计思路
  • 芜湖公司网站建设wordpress无限地址
  • 冠县网站建设gxsh如何建设一个属于自己的网站
  • 通信网站建设关于建设集团公司网站的报告
  • 江苏省建设工程上岗证查询网站WordPress增加文章来源插件
  • jsp网站建设 书籍有什么网站交互做的很好 知乎
  • 在哪个网站开发外贸业务网站注销主体填写原因
  • 用python写一个简单的网页seo推广公司教程
  • 常州钟楼区邹区建设局网站网站运营怎么样
  • 栾川网站开发微信小程序脚本
  • 网站设计制作策划书韩国做 mp4下载网站
  • 网站建设客户调查需求表wordpress 5.0.2
  • 校园网二手书交易网站建设重庆介绍ppt制作
  • 湛江市建设教育协会学校网站wordpress视频教程百度网盘
  • 网站开发需要服务器吗做3d图的网站有哪些软件
  • 中国建设银行官方网站下载wordpress 自动分页
  • 课程平台网站建设报价岫岩洋河网站建设
  • 山东地产网站建设网站建设 招标任务书
  • 医院网站建设解决方案网站后台更新前台不显示
  • 关于做网站的策划书网络营销需要学什么
  • 可以免费做兼职的网站有哪些游戏门户网站建设
  • 家具公司网站模板网站规划与开发技术专业
  • 山东网站建设方案制作asp新闻发布网站模板下载
  • wordpress仿站软件大学科技园东区 做网站
  • 怎么做电子商务的网站推广做侵权网站用哪里的服务器
  • 小公司做网站需要注意什么问题我做夫人那些年网站登录
  • 中国建设银行报网站免费永久域名申请注册
  • 关于网站建设 策划文案在俄罗斯用钱让女性做h事情的网站