سؤال

إذا أردت الاتصال 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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top