为什么从函数返回对象时会得到两个临时对象 这是我的C++代码< /p> 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; }
我通过查看汇编代码发现有两个临时对象为什么从函数返回对象时会得到两个临时对象 这是我的C++代码< /p> 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; },c++,assembly,x86,C++,Assembly,X86,我通过查看汇编代码发现有两个临时对象 //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) 000
//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?)
“为什么我得到了第二个临时对象”
这可能是因为您关闭了优化
否则,编译器将通过将main中的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;
}
这种优化称为按值返回优化它是返回和赋值(复制)。您的编译器显然没有执行复制省略。您是否使用优化编译代码?使用优化,我的编译器将main编译为:
xor eax,eax;ret
。谢谢您的评论。是的,我正在调试模式下学习汇编,没有优化。第一个临时文件用于返回,第二个临时文件用于赋值,对吗?这是哪个编译器?是msvc吗?转换不会用赋值代替构造。代码看起来更像:(void*)把结果放在这里
和{obj=*(new(把结果放在这里)CTest);obj.number=val;}
,但是在main
中不会有obj
的构造。试图为此编写伪代码(IMHO)是非常误导的。