다른 함수의 반환을 반환합니다
-
03-07-2019 - |
문제
전화하고 싶다면 Bar()
대신에 Foo()
, 하다 Bar()
foo ()가 반환하는 것에 대한 사본 (추가 오버 헤드)을 반환하거나 동일한 개체를 반환합니다. Foo()
임시 스택에 장소?
vector<int> Foo(){
vector<int> result;
result.push_back(1);
return result;
}
vector<int> Bar(){
return Foo();
}
해결책
둘 다 일어날 수 있습니다. 그러나 대부분의 컴파일러는 최적화하자마자 복사하지 않습니다.
코드에 사본이 있어야합니다. 그러나 컴파일러는 시맨틱과 프로그램을 변경하지 않는 사본을 제거 할 수 있습니다.
참고 : 이것이 사본이 실제로 완료 될지 여부를 확신 할 수 없으므로 올바르게 복사하는 것 외에는 아무것도 수행하는 사본 생성자가 없어야하는 이유입니다.
다른 팁
이것은 NRVO의 사소한 사례입니다 - 이름 리턴 값 최적화 (이름이 없기 때문에이 경우 오해). 스탠 립만 모자 a 블로그 항목 관련된 메커니즘에 대한 좋은 설명으로.
일반적으로 반환 된 사본을 반환합니다 vector<int>
. 그러나 이것은 컴파일러가 수행 한 최적화에 크게 달려 있습니다. 다음 토론을 참조하십시오.
디버그 빌드
vector<int> Foo(){
004118D0 push ebp
004118D1 mov ebp,esp
004118D3 push 0FFFFFFFFh
004118D5 push offset __ehhandler$?Foo@@YA?AV?$vector@HV?$allocator@H@std@@@std@@XZ (419207h)
004118DA mov eax,dword ptr fs:[00000000h]
004118E0 push eax
004118E1 sub esp,0F4h
004118E7 push ebx
004118E8 push esi
004118E9 push edi
004118EA lea edi,[ebp-100h]
004118F0 mov ecx,3Dh
004118F5 mov eax,0CCCCCCCCh
004118FA rep stos dword ptr es:[edi]
004118FC mov eax,dword ptr [___security_cookie (41E098h)]
00411901 xor eax,ebp
00411903 push eax
00411904 lea eax,[ebp-0Ch]
00411907 mov dword ptr fs:[00000000h],eax
0041190D mov dword ptr [ebp-0F0h],0
vector<int> result;
00411917 lea ecx,[ebp-24h]
0041191A call std::vector<int,std::allocator<int> >::vector<int,std::allocator<int> > (411050h)
0041191F mov dword ptr [ebp-4],1
result.push_back(1);
00411926 mov dword ptr [ebp-0FCh],1
00411930 lea eax,[ebp-0FCh]
00411936 push eax
00411937 lea ecx,[ebp-24h]
0041193A call std::vector<int,std::allocator<int> >::push_back (41144Ch)
return result;
0041193F lea eax,[ebp-24h]
00411942 push eax
00411943 mov ecx,dword ptr [ebp+8]
00411946 call std::vector<int,std::allocator<int> >::vector<int,std::allocator<int> > (41104Bh)
0041194B mov ecx,dword ptr [ebp-0F0h]
00411951 or ecx,1
00411954 mov dword ptr [ebp-0F0h],ecx
0041195A mov byte ptr [ebp-4],0
0041195E lea ecx,[ebp-24h]
00411961 call std::vector<int,std::allocator<int> >::~vector<int,std::allocator<int> > (411415h)
00411966 mov eax,dword ptr [ebp+8]
}
여기서 우리는 그것을 볼 수 있습니다 vector<int> result;
스택에 새 객체가 생성됩니다 [ebp-24h]
00411917 lea ecx,[ebp-24h]
0041191A call std::vector<int,std::allocator<int> >::vector<int,std::allocator<int> > (411050h)
우리가 가면 return result;
발신자가 할당 한 스토리지에서 새 사본이 생성됩니다. [ebp+8]
00411943 mov ecx,dword ptr [ebp+8]
00411946 call std::vector<int,std::allocator<int> >::vector<int,std::allocator<int> > (41104Bh)
그리고 소멸자는 로컬 매개 변수를 요구합니다 vector<int> result
~에 [ebp-24h]
0041195E lea ecx,[ebp-24h]
00411961 call std::vector<int,std::allocator<int> >::~vector<int,std::allocator<int> > (411415h)
릴리스 빌드
vector<int> Foo(){
00401110 push 0FFFFFFFFh
00401112 push offset __ehhandler$?Foo@@YA?AV?$vector@HV?$allocator@H@std@@@std@@XZ (401F89h)
00401117 mov eax,dword ptr fs:[00000000h]
0040111D push eax
0040111E sub esp,14h
00401121 push esi
00401122 mov eax,dword ptr [___security_cookie (403018h)]
00401127 xor eax,esp
00401129 push eax
0040112A lea eax,[esp+1Ch]
0040112E mov dword ptr fs:[00000000h],eax
00401134 mov esi,dword ptr [esp+2Ch]
00401138 xor eax,eax
0040113A mov dword ptr [esp+8],eax
vector<int> result;
0040113E mov dword ptr [esi+4],eax
00401141 mov dword ptr [esi+8],eax
00401144 mov dword ptr [esi+0Ch],eax
result.push_back(1);
return result;
00401147 push eax
00401148 mov dword ptr [esp+28h],eax
0040114C mov ecx,1
00401151 push esi
00401152 lea eax,[esp+14h]
00401156 mov dword ptr [esp+10h],ecx
0040115A mov dword ptr [esp+14h],ecx
0040115E push eax
0040115F lea ecx,[esp+1Ch]
00401163 push ecx
00401164 mov eax,esi
00401166 call std::vector<int,std::allocator<int> >::insert (401200h)
0040116B mov eax,esi
}
0040116D mov ecx,dword ptr [esp+1Ch]
00401171 mov dword ptr fs:[0],ecx
00401178 pop ecx
00401179 pop esi
0040117A add esp,20h
0040117D ret
라인 vector<int> result
벡터 할당자가 호출 사이트에서 수행되므로 벡터 할당을 호출하지 않습니다. Bar
. 최적화는 FOO의 결과 사본을 만들지 않습니다.