int&at()
int上面兩個函式,第乙個返回值是int的引用int&,第二個返回值是int,二者的區別是什麼呢?at()
我們先用乙個語句 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++不保證這種優化一定會做。
C 返回物件和返回引用
最大的區別在於,返回物件的話會在記憶體中根據返回的型別開闢一塊區域,用返回的值對該記憶體進行初始化,如果是返回的物件,利用拷貝構造來初始化這個區域,但是這塊區域並沒有名字,就是說之後使用者沒辦法訪問到這個區域,也成為無名變數,它只能在接下來的 中進行一次性的用途,要不作為引數傳遞,或者將值列印,再之...
C 返回物件和返回引用
我們發現,在c 中,有些成員函式返回的是物件,而有些函式返回的又是引用。返回物件和返回引用的最主要的區別就是函式原型和函式頭。car run const car 返回物件 car run const car 返回引用 返回物件會涉及到生成返回物件的副本。因此,返回物件的時間成本包括了呼叫複製建構函式...
不能返回區域性變數的引用
源之 int add1 int a,int b int add2 int a,int b 請問這兩個函式返回有什麼區別,是乙個返回副本,另乙個直接返回嗎?呼叫函式add2有什麼危險嗎?add1的確返回了乙個副本,如果sum是自定義的類型別,可以很明顯看出拷貝建構函式在返回時被呼叫,對於內建型別沒什麼...