2008-10-03 18 views
7

की वापसी लौटने मैं Foo() के बजाय Bar() कॉल करने के लिए चाहते हैं समारोह, Bar() मुझे क्या फू() रिटर्न की एक प्रति (अतिरिक्त भूमि के ऊपर) वापसी करता है, या यह एक ही वस्तु देता है जो अस्थायी स्टैक पर Foo() स्थानों ?एक और समारोह

vector<int> Foo(){ 
    vector<int> result; 
    result.push_back(1); 
    return result; 
} 
vector<int> Bar(){ 
    return Foo(); 
} 

उत्तर

10

दोनों हो सकते हैं। हालांकि, जैसे ही आप अनुकूलित करते हैं, अधिकांश संकलक प्रतिलिपि नहीं करेंगे।

आपका कोड इंगित करता है कि एक प्रति होना चाहिए। हालांकि, कंपाइलर को ऐसी किसी भी प्रति को हटाने की अनुमति है जो अर्थपूर्ण और प्रोग्राम को परिवर्तित न करे।

नोट: यही कारण है कि आपको कभी भी एक प्रतिलिपि बनाने वाला नहीं होना चाहिए जो कुछ भी करता है लेकिन सही ढंग से प्रतिलिपि बना रहा है क्योंकि आप कभी भी सुनिश्चित नहीं हो सकते कि एक प्रति वास्तव में किया जाएगा या नहीं।

+0

दुर्भाग्य से यह ऐसी जगह नहीं है जहां संकलक को कॉपी को हटाने की अनुमति है (इनलाइनिंग हालांकि इसे हटा देगी)। तो हाँ एक वेक्टर को फू() से बार() तक कॉपी किया गया है, फिर बार() से कॉलर तक कॉपी किया गया है। Std :: vector <> को बहुत कुशल बनाने के लिए बहुत सारे काम किए गए हैं। तो चिंता मत करो। –

+0

मुझे लगता है कि संकलक रिटर्न वैल्यू ऑप्टिमाइज़ेशन (http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx) का उपयोग कर एक ही प्रति के रूप में इसे सुरक्षित रूप से अनुकूलित कर सकता है। मूल रूप से यदि चर का निर्माण किया जाएगा और तुरंत प्रतिलिपि बनाई जाएगी, तो यह केवल उस स्थान पर सीधे निर्माण कर सकती है जहां इसकी प्रतिलिपि बनाई जाएगी। –

+0

यह बिल्कुल एक ऐसा स्थान है जहां ऑप्टिमाइज़ेशन होता है, यहां तक ​​कि इनलाइनिंग के बिना भी। – PierreBdR

2

सामान्य रूप से इसे वापस आ vector<int> की एक प्रति देता है। हालांकि यह संकलक द्वारा किए गए अनुकूलन पर निर्भर करता है। निम्नलिखित चर्चा देखें।

डीबग बिल्ड

vector<int> Foo(){ 
004118D0 push  ebp 
004118D1 mov   ebp,esp 
004118D3 push  0FFFFFFFFh 
004118D5 push  offset [email protected]@[email protected][email protected]@[email protected]@@[email protected]@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) 
पर कॉलर द्वारा आवंटित संग्रहण

और क्योंकि उस में कॉल साइट पर किया जाता है नाशक [ebp-24h]

0041195E lea   ecx,[ebp-24h] 
00411961 call  std::vector<int,std::allocator<int> >::~vector<int,std::allocator<int> > (411415h) 

रिलीज पर स्थानीय पैरामीटर vector<int> result के लिए कहा जाता है

vector<int> Foo(){ 
00401110 push  0FFFFFFFFh 
00401112 push  offset [email protected]@[email protected][email protected]@[email protected]@@[email protected]@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 से परिणाम की कोई प्रति नहीं बनाता है।

+0

मुझे लगता है कि यह स्पष्टीकरण थोड़ा अधिक है ... और अत्यधिक संकलक पर निर्भर करता है। – PierreBdR

2

यह एनआरवीओ के लिए एक मामूली मामला है - नाम वापसी मूल्य अनुकूलन (इस मामले में कोई गलत नाम नहीं है क्योंकि कोई नाम नहीं है)। स्टेन लिपमैन टोपी blog entry शामिल तंत्र की एक अच्छी व्याख्या के साथ।

+1

अस्थायी नाम नहीं होने पर इसे आरवीओ कहा जाता है। –

+0

अच्छा लेख, धन्यवाद। – jonner

+1

@ डेविड: हाँ, कुछ लोगों द्वारा, और मैं इसे स्वयं कहता था। हालांकि, तकनीकी साहित्य में "आरवीओ" का कोई उल्लेख नहीं है। "एनआरवीओ" का प्रयोग तकनीकी शब्द के रूप में किया जाता है। –

संबंधित मुद्दे