17

कॉपी इस कार्यक्रमसी ++ कॉपी निर्माता, temporaries और शब्दों को

#include <iostream> 
using std::cout; 

struct C 
{ 
    C() { cout << "Default C called!\n"; } 
    C(const C &rhs) { cout << "CC called!\n"; } 
}; 

const C f() 
{ 
    cout << "Entered f()!\n"; 
    return C(); 
} 

int main() 
{ 
    C a = f(); 
    C b = a; 

    return 0; 
} 

उत्पादन मैं मिलता है के लिए:

Entered f()! 
Default C called! 
CC called! 

f() के बाद से मूल्य से लौटा रहा है, यह एक अस्थायी लौटना चाहिए। T a = x; रूप T a(x); है, यह अस्थायी साथ, a के निर्माण के लिए प्रति निर्माता फोन नहीं होगा पारित कर दिया-अपने तर्क के रूप में?

उत्तर

14

f() के बाद से मूल्य से लौटा रहा है, यह एक अस्थायी लौटना चाहिए। T a = x; रूप T a(x); है, यह अस्थायी साथ, a के निर्माण के लिए प्रति निर्माता फोन नहीं होगा पारित कर दिया-अपने तर्क के रूप में?

वापसी मूल्य अनुकूलन देखें। यह डिफ़ॉल्ट रूप से चालू है। आप MSVC का उपयोग कर विंडोज पर हैं, तो 2005+ आप (या -fno-elide-constructors जीसीसी पर) इस बंद कर देते हैं और वांछित परिणाम प्राप्त करने के लिए /Od उपयोग कर सकते हैं। इसके अलावा, एमएसवीसी के लिए this आलेख देखें।

12,8 प्रतिलिपि बनाई जा रही वर्ग वस्तुओं

जब कुछ मानदंडों को पूरा किया जाता है, एक कार्यान्वयन एक वर्ग वस्तु के प्रतिलिपि निर्माण, छोड़ करने की अनुमति है भले ही प्रति निर्माता और/या ऑब्जेक्ट के लिए विनाशक के पास प्रभाव हैं। ऐसे मामलों में, कार्यान्वयन स्रोत और छोड़े गए प्रतिलिपि आपरेशन के रूप में बस दो अलग अलग तरीकों एक ही वस्तु की चर्चा करते हुए की लक्ष्य व्यवहार करता है, और उस वस्तु की विनाश पर कई बार बाद में तब होता है जब दो ऑब्जेक्ट्स अनुकूलन के बिना नष्ट हो गए होंगे।115 प्रति आपरेशन के इस इलिजन निम्नलिखित परिस्थितियों में अनुमति दी है ( कई प्रतियां खत्म करने के लिए संयुक्त हो सकता है):

- एक वर्ग वापसी प्रकार के साथ एक समारोह में एक वापसी बयान में, जब अभिव्यक्ति सीधे समारोह के पुनर्निर्वाचन में समारोह वापसी प्रकार के रूप में ही सीवी-अयोग्य प्रकार के साथ एक नॉन-वोलाटाइल स्वत: वस्तु, नकल आपरेशन स्वचालित वस्तु निर्माण द्वारा छोड़ा जा सकता है का नाम है मूल्य बारी - एक थ्रो-अभिव्यक्ति में, जब संकार्य एक नॉन-वोलाटाइल स्वत: वस्तु का नाम है, अपवाद वस्तु (15.1) के लिए संकार्य से प्रतिलिपि आपरेशन स्वत: निर्माण करके छोड़ा जा सकता है अपवाद वस्तु

में सीधे वस्तु - जब एक अस्थायी वर्ग वस्तु है कि एक संदर्भ के लिए बाध्य नहीं किया गया (12.2) के साथ एक वर्ग वस्तु में कॉपी किया जाएगा एक ही सीवी-अयोग्य प्रकार, प्रतिलिपि ऑपरेशनद्वारा छोड़ा जा सकता है छोड़े गए प्रतिलिपि

का लक्ष्य में सीधे अस्थायी वस्तु निर्माण - जब एक अपवाद हैंडलर (खण्ड 15) की अपवाद-घोषणा एक ही प्रकार के एक वस्तु वाणी ( सीवी-योग्यता के अलावा) अपवाद वस्तु (15.1) के रूप में, प्रतिलिपि आपरेशन अपवाद वस्तु के लिए एक उपनाम के रूप अपवाद-घोषणा के इलाज अगर का अर्थ कार्यक्रम निर्माताओं के निष्पादन के लिए को छोड़कर कोई बदलाव नहीं हो सकता है और होगा द्वारा छोड़ा जा सकता है ऑब्जेक्ट के लिए विनाशक द्वारा घोषित अपवाद-घोषणा।

नोट: जोर मेरा

+0

मैं जीसीसी का उपयोग करता हूं, और '-फनो-एलिइड-कन्स्ट्रक्टर' के साथ यह दिखाता है कि हुड के नीचे क्या हो रहा है! कभी-कभी ये अनुकूलन एक शिक्षार्थी को बहुत भ्रमित करते हैं :) हालांकि, मैं मानता हूं कि उन्हें डिफ़ॉल्ट रूप से चालू होना चाहिए, फिर से एक अनौपचारिक व्यक्ति का निर्माण डिफ़ॉल्ट रूप से अनुकूलित किया जाएगा। – legends2k

+0

@ किंवदंतियों 2k: आरवीओ उपयोगकर्ताओं के सनकी के लिए छोड़ने के लिए बहुत उपयोगी है।इसके अलावा, यह बहुत कम उदाहरणों में से एक है जहां मानक अनुकूलन की अनुमति देता है। यह पुन: उत्साहित करता है कि यह क्यों छोड़ा गया है। हालांकि, ध्यान दें कि यह सामान्य रूप से अन्य अनुकूलन के बारे में सच नहीं है। – dirkgently

+0

सहमत, बिंदु ले लिया। विकी लिंक के लिए – legends2k

4

यह रिटर्न वैल्यू ऑप्टिमाइज़ेशन (आरवीओ) सुविधाओं का एक उदाहरण है जो आपके कंपाइलर का समर्थन करता है।

एक कॉपी कन्स्ट्रक्टर को मूल्य से वापस आने पर कॉल नहीं किया जा सकता है। जीसीसी पर

उपयोग -fno-elide-constructors विकल्प है कि सुविधा को बंद करने।

+0

+1! – legends2k

2

मेरा मानना ​​है कि यह return value optimization कहा जाता है।

मुझे लगता है जब f() रिटर्न आपत्ति C वस्तु बुला विधि इसलिए कोई प्रतिलिपि C a प्रारंभ करने की आवश्यकता है के ढेर अंतरिक्ष में आवंटित किया जाता है। यह आपका default C called है।

C b = a 

यह एक प्रतिलिपि बनाता है इसलिए आपका CC called

बीटीडब्ल्यू, विकी पर उदाहरण आपके कोड के समान दिखता है। त्वरित उत्तर के लिए

+0

+1। ऊप्स! यहां तक ​​कि नामकरण समान दिखता है, लेकिन मैं कसम खाता हूं कि मैंने इसे पढ़ने के बाद पोस्ट नहीं किया है, मैं C++ _ में _Thinking पढ़ रहा हूं :) – legends2k

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