您好,欢迎来到好走旅游网。
搜索
您的当前位置:首页C++中返回引用和返回值的区别

C++中返回引用和返回值的区别

来源:好走旅游网
C++中返回引⽤和返回值的区别

转⾃

⼀、主要讨论下⾯两个函数的区别:

int& at(){

return m_data_;}

int at(){

return m_data_;}

上⾯两个函数,第⼀个返回值是int的引⽤int&,第⼆个返回值是int,⼆者的区别是什么呢?

我们先⽤⼀个语句 const int& a = mymay.at(); 来分别调⽤⼀次上⾯两个函数,然后看汇编语⾔的结果。反汇编结果:

1 #int& at() 2 #{

3 # return m_data_; 4 #} 5

6 00BB6830 push ebp

7 00BB6831 mov ebp,esp 8 00BB6833 sub esp,0CCh 9 00BB6839 push ebx 10 00BB683A push esi 11 00BB683B push edi 12 00BB683C push ecx

13 00BB683D lea edi,[ebp-0CCh] 14 00BB6843 mov ecx,33h

15 00BB6848 mov eax,0CCCCCCCCh 16 00BB684D rep stos dword ptr es:[edi] 17 00BB684F pop ecx

18 00BB6850 mov dword ptr [this],ecx 19 m_data_++;

20 00BB6853 mov eax,dword ptr [this] 21 00BB6856 mov ecx,dword ptr [eax] 22 00BB6858 add ecx,1

23 00BB685B mov edx,dword ptr [this] 24 00BB685E mov dword ptr [edx],ecx 25 return m_data_;

26 #取地址this中的值5879712(m_data_的地址)到寄存器eax中,此时寄存器eax存的是m_data_的地址27 00BB6860 mov eax,dword ptr [this] 28 }

29 00BB6863 pop edi 30 00BB68 pop esi 31 00BB6865 pop ebx

32 00BB6866 mov esp,ebp 33 00BB6868 pop ebp 34 00BB6869 ret 35 36 37 38 39

40 const int& a = mymay.at(); 41 00176AA2 lea ecx,[mymay]

42 00176AA5 call MyMat::at (01716h)

43 #此时寄存器eax中的值为m_data_的地址5879712,直接将地址5879712存⼊地址a中。44 00176AAA mov dword ptr [a],eax 45 cout << a << endl; 1 #int at() 2 #{

3 # return m_data_; 4 #} 5 6

7 012B6830 push ebp

8 012B6831 mov ebp,esp 9 012B6833 sub esp,0CCh 10 012B6839 push ebx 11 012B683A push esi 12 012B683B push edi 13 012B683C push ecx

14 012B683D lea edi,[ebp-0CCh] 15 012B6843 mov ecx,33h

16 012B6848 mov eax,0CCCCCCCCh 17 012B684D rep stos dword ptr es:[edi] 18 012B684F pop ecx

19 012B6850 mov dword ptr [this],ecx 20 return m_data_;

21 #和上⾯⼀样,也是先取出m_data_的地址22 012B6853 mov eax,dword ptr [this]

23 #和上⾯不⼀样,不是直接将m_data_的地址放⼊寄存器eax中,⽽是取地址5879712中的值(m_data_=3)放⼊寄存器eax中,此时寄存器eax存的是m_data_的值(3)24 012B6856 mov eax,dword ptr [eax] 25 }

26 012B6858 pop edi 27 012B6859 pop esi 28 012B685A pop ebx

29 012B685B mov esp,ebp 30 012B685D pop ebp 31 012B685E ret 32 33 34 35 36

37 const int& a = mymay.at(); 38 008E6AA2 lea ecx,[mymay]

39 008E6AA5 call MyMat::at (08E1Bh) 40 #此时eax的值为3,将3存⼊地址ebp-24h中,41 008E6AAA mov dword ptr [ebp-24h],eax 42 #将eax的值变成ebp-24h

43 008E6AAD lea eax,[ebp-24h]

44 #将地址ebp-24h写到地址为a中,此时a代表的地址是ebp-24h45 008E6AB0 mov dword ptr [a],eax 46 cout << a << endl;

所以结论就是:

1、返回值为引⽤型(int& )的时候,返回的是地址,因为这⾥⽤的是 int& a=mymay.at(); ,所以a和m_data_指的是同⼀块地址(由寄存器eax传回的5879712)。

2、返回值不是引⽤型(int)的时候,返回的是⼀个数值。这个时候就很有意思了,编译器是先将这个数值放⼊⼀个内存中(上⾯例⼦中,该内存地址为ebp-24h),再把这个地址付给a,此时的a代表的地址是ebp-24h,和m_data_代表的地址不⼀样(m_data_代表的地址是5879712)。

3、综上两点可以看出,当返回的值不是引⽤型时,编译器会专门给返回值分配出⼀块内存的(例⼦中为ebp-24h)。

⼆、说明⼀下函数返回时,如果不是返回⼀个变量的引⽤,则⼀定会⽣成⼀个临时变量。

看下⾯的函数,返回的是t⽽不是&t,所以⼀定会有临时变量产⽣。

1 T function1(){2 T t(0);3 return t;4 }

5 T x=function1();

这⾥的过程是:1.创建命名对象t

2.拷贝构造⼀个⽆名的临时对象,并返回这个临时对象3.由临时对象拷贝构造对象x

4.T x=function1();这句语句结束时,析构临时对象

这⾥⼀共⽣成了3个对象,⼀个命名对象t,⼀个临时对象作为返回值,⼀个命名对象x。

下⾯的函数稍微复杂⼀定,它没有先定义⼀个中间变量t,看起来似乎是直接返回了⼀个临时变量。但实际上,如果不经过c++的优化,那么它并没有提⾼效率,因为它还是创建了3个对象。

1 T function2(){2 return T(0);3 }

4 T x=function2();

这⾥的过程是:1.创建⼀个⽆名对象

2.由⽆名对象拷贝构造⼀个⽆名的临时对象3.析构⽆名对象,返回临时对象4.由临时对象拷贝构造对象x

5.T x=function2()语句结束时,析构临时对象。

这⾥⼀共⽣成了3个对象,其中有2个对象都是马上被析构掉的,不能被后⾯的代码使⽤。既然是这样,那么就会有优化的余地,可以尝试着不要前⾯的两个临时变量。c++确实会做这样的优化,优化后的c++会避免匿名对象和临时对象这两个对象的⽣成,⽽直接⽣成x,这样就减少了两次对象⽣成-回收的消耗,提⾼了程序性能。

其实function1()这段代码也是会经过优化的,但因为临时对象t是⼀个命名对象,所以⼀定会被创建。存储返回值的临时对象是多余的,会被优化掉⽽不⽣成。

但是,程序员不应该依赖这种优化,因为c++不保证这种优化⼀定会做。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- haog.cn 版权所有 赣ICP备2024042798号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务