int&at()
intat()
上面兩個函式,第乙個返回值是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 #intat()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,所以一定會有臨時變數產生。
1t function1()
5 t x=function1();
這裡的過程是:
1.建立命名物件t
2.拷貝構造乙個無名的臨時物件,並返回這個臨時物件
3.由臨時物件拷貝構造物件x
4.t x=function1();這句語句結束時,析構臨時物件
這裡一共生成了3個物件,乙個命名物件t,乙個臨時物件作為返回值,乙個命名物件x。
下面的函式稍微複雜一定,它沒有先定義乙個中間變數t,看起來似乎是直接返回了乙個臨時變數。但實際上,如果不經過c++的優化,那麼它並沒有提高效率,因為它還是建立了3個物件。
1t 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...