C 函式中返回引用和返回值的區別

2022-05-08 07:06:14 字數 4535 閱讀 6400

int&at()

int

at()

上面兩個函式,第乙個返回值是int的引用int&,第二個返回值是int,二者的區別是什麼呢?

我們先用乙個語句 const int& a = mymay.at();

來分別呼叫一次上面兩個函式,然後看組合語言的結果。

反彙編結果:

1 #int

& at()2#

5600bb6830

push

ebp

700bb6831

movebp,esp

800bb6833

subesp,0cch

900bb6839

push

ebx

1000bb683a

push

esi

1100bb683b

push

edi

1200bb683c

push

ecx

1300bb683d

leaedi,[ebp-0cch]

1400bb6843

movecx,33h

1500bb6848

moveax,0cccccccch

1600bb684d

rep stos dword ptr es:

[edi]

1700bb684f

popecx

1800bb6850

movdword ptr [this],ecx

19 m_data_++;

2000bb6853

moveax,dword ptr [this]

2100bb6856

movecx,dword ptr [eax]

2200bb6858

add ecx,1

2300bb685b

movedx,dword ptr [this]

2400bb685e

movdword ptr [edx],ecx

25 return m_data_;

26#取位址this中的值5879712(m_data_的位址)到暫存器eax中,此時暫存器eax存的是m_data_的位址

2700bb6860

moveax,dword ptr [this] 28}

2900bb6863

popedi

3000bb6864

popesi

3100bb6865

popebx

3200bb6866

movesp,ebp

3300bb6868

popebp

3400bb6869

ret35

3637

3839

40 const int& a = mymay.at();

4100176aa2

leaecx,[mymay]

4200176aa5

call

mymat:

:at (0171546h)

43 #此時暫存器eax中的值為m_data_的位址5879712,直接將位址5879712存入位址a中。

4400176aaa

movdword ptr [a],eax

45 cout << a << endl;

1 #int

at()2#

567012b6830

push

ebp

8012b6831

movebp,esp

9012b6833

subesp,0cch

10012b6839

push

ebx

11012b683a

push

esi

12012b683b

push

edi

13012b683c

push

ecx

14012b683d

leaedi,[ebp-0cch]

15012b6843

movecx,33h

16012b6848

moveax,0cccccccch

17012b684d

rep stos dword ptr es:

[edi]

18012b684f

popecx

19012b6850

movdword ptr [this],ecx

20 return m_data_;

21#和上面一樣,也是先取出m_data_的位址

22012b6853

moveax,dword ptr [this]

23 #和上面不一樣,不是直接將m_data_的位址放入暫存器eax中,而是取位址5879712中的值(m_data_=3)放入暫存器eax中,此時暫存器eax存的是m_data_的值(3)24

012b6856

moveax,dword ptr [eax] 25}

26012b6858

popedi

27012b6859

popesi

28012b685a

popebx

29012b685b

movesp,ebp

30012b685d

popebp

31012b685e

ret32

3334

3536

37 const int& a = mymay.at();

38008e6aa2

leaecx,[mymay]

39008e6aa5

call

mymat:

:at (08e154bh)

40#此時eax的值為3,將3存入位址ebp-24h中,

41008e6aaa

movdword ptr [ebp-24h],eax

42#將eax的值變成ebp-24h

43008e6aad

leaeax,[ebp-24h]

44#將位址ebp-24h寫到位址為a中,此時a代表的位址是ebp-24h

45008e6ab0

movdword 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()

5 t x=function1();

這裡的過程是:

1.建立命名物件t

2.拷貝構造乙個無名的臨時物件,並返回這個臨時物件

3.由臨時物件拷貝構造物件x

4.t x=function1();這句語句結束時,析構臨時物件

這裡一共生成了3個物件,乙個命名物件t,乙個臨時物件作為返回值,乙個命名物件x。

下面的函式稍微複雜一定,它沒有先定義乙個中間變數t,看起來似乎是直接返回了乙個臨時變數。但實際上,如果不經過c++的優化,那麼它並沒有提高效率,因為它還是建立了3個物件。

1

t function2()

4 t x=function2();

這裡的過程是:

1.建立乙個無名物件

2.由無名物件拷貝構造乙個無名的臨時物件

3.析構無名物件,返回臨時物件

4.由臨時物件拷貝構造物件x

5.t x=function2()語句結束時,析構臨時物件。

這裡一共生成了3個物件,其中有2個物件都是馬上被析構掉的,不能被後面的**使用。既然是這樣,那麼就會有優化的餘地,可以嘗試著不要前面的兩個臨時變數。c++確實會做這樣的優化,優化後的c++會避免匿名物件和臨時物件這兩個物件的生成,而直接生成x,這樣就減少了兩次物件生成-**的消耗,提高了程式效能。

其實function1()這段**也是會經過優化的,但因為臨時物件t是乙個命名物件,所以一定會被建立。儲存返回值的臨時物件是多餘的,會被優化掉而不生成。

但是,程式設計師不應該依賴這種優化,因為c++不保證這種優化一定會做。

函式返回值總結 (返回指標和引用的區別)

例1 cpp view plain copy print?class a int get a func int main class a int get a func int main a func int main class a a func int main class a a func in...

c 引用返回值

函式返回值時,要生成乙個值的副本。而用引用返回值時,不生成值的副本。例如,下面的程式是有關引用返回的4種形式 ch9 6.cpp include float temp float fn1 float r float fn2 float r void main void main 見圖9 9說明。圖9...

c 引用返回值

引用作為函式的返回值時,函式的返回值能夠理解為函式返回了乙個變數 事實上,函式返回引用時,它返回的是乙個指向返回值的隱式指標 因此,值為引用的函式能夠用作賦值運算子的左運算元。另外,用引用返回乙個函式值的最大優點是。在記憶體中不產生被返回值的副本。include using namespace st...