وظيفة إرجاع عودة وظيفة أخرى
-
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 - أسماء إرجاع قيمة إرجاع التحسين (تسمية خاطئة في هذه الحالة لأنه لا يوجد اسم). قبعة ستان ليبمان أ إدخال المدونة مع شرح لطيف للآلية المعنية.
عادةً ما يعيد نسخة من العائد 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.