2013-07-28 73 views
4

這是我的C++代碼爲什麼我從一個函數返回一個對象時,有兩個臨時對象

class CTest { 
public: 
    int number; 
    int arr[10]; 
}; 

CTest Return(int val) { 
    CTest obj; 
    obj.number = val; 
    return obj; 
} 

int main() { 
    CTest obj = Return(10); 
    return 0; 
} 

我發現,存在由觀察彙編代碼的兩個臨時對象

//in main 

    CTest obj = Return(10); 
0009F6CE push  0Ah 
0009F6D0 lea   eax,[ebp-158h] ; pass the first temporary object's address to Return 
0009F6D6 push  eax 
0009F6D7 call  Return (0822E9h) 
0009F6DC add   esp,8 
0009F6DF mov   ecx,0Bh 
0009F6E4 mov   esi,eax 
0009F6E6 lea   edi,[ebp-124h] ; copy from the first temporary object 
0009F6EC rep movs dword ptr es:[edi],dword ptr [esi] 
0009F6EE mov   ecx,0Bh 
0009F6F3 lea   esi,[ebp-124h] 
0009F6F9 lea   edi,[obj]  ; copy from the second temporary object 
0009F6FC rep movs dword ptr es:[edi],dword ptr [esi] 

//in Return 

    CTest obj; 
    obj.number = val; 
0009F64E mov   eax,dword ptr [val] 
0009F651 mov   dword ptr [obj],eax 
    return obj; 
0009F654 mov   ecx,0Bh 
0009F659 lea   esi,[obj] 
0009F65C mov   edi,dword ptr [ebp+8] 
0009F65F rep movs dword ptr es:[edi],dword ptr [esi] ; copy to the first temporary object 
0009F661 mov   eax,dword ptr [ebp+8] 

爲什麼我得到了第二個臨時對象。似乎只有一個臨時對象就夠了。如果我添加一個空的析構函數~CTest() {}將不會有臨時對象(RVO?)。

+3

這是返回和分配(複製)。你的編譯器顯然沒有執行copy elision。 – 2013-07-28 09:26:56

+5

您是否使用優化編譯代碼? –

+4

通過優化,我的編譯器將main編譯爲:'xor eax,eax; ret'。 –

回答

0

「爲什麼我得到了第二次臨時對象」

這可能是因爲你關掉了優化。

否則,編譯器會通過將主參數obj作爲隱藏參數(與指針this一樣)傳遞給返回函數進行優化,併爲其分配「結果」。

所以優化後你的代碼看起來就像這樣:

void Return(void* put_result_here , int val) { 
    CTest obj; 
    obj.number = val; 
    put_result_here = obj; 
} 


int main() { 
    CTest obj; 
    Return(&obj , 10); 
    return 0; 
} 

這種優化稱爲返回由價值優化

+5

轉型不會取代建築與轉讓。代碼看起來更像:'(void *)put_result_here'和'{obj = *(new(put_result_here)CTest); obj.number = val; }'但''main'中不會構造'obj'。試圖爲此僞代碼是(恕我直言)非常誤導。 –

相關問題