दिलचस्प पोस्ट
स्टैक अतिप्रवाह कैसे अपने एसईओ के अनुकूल यूआरएल उत्पन्न करता है? कैमरे से पूर्वावलोकन के बिना चित्र लेना तकनीकी रूप से एस 3 एन, एस 3 ए और एस 3 में अंतर क्या है? Scikit में कई कॉलम में लेबल एन्कोडिंग सीखें आईफोन पर वर्तमान स्थानीय समय प्राप्त करना? त्रुटि: प्रकार त्रुटि: $ (…) .dialog फ़ंक्शन नहीं है XML दस्तावेज़ों में भाग लेने के लिए मुझे कौन-कौन से पात्रों की आवश्यकता है? WebView में लंबेक्लिक करें सक्षम करें अजगर के साथ बीडीडी का अभ्यास जावा कैलेंडर, दिनांक, और बहु-टाइमज़न अनुप्रयोग के लिए समय प्रबंधन पेंडस मल्टी इंडेक्स के स्तर को अपने डेटाफ़्रेम को टुकड़े टुकड़े करने के बाद कैसे अपडेट कर सकते हैं? UIView में रेखा खींचें मैं जावास्क्रिप्ट पाश में देरी कैसे जोड़ूं? मैं Raphael javascript पुस्तकालय में ऑब्जेक्ट कैसे जोड़ सकता हूं? एसटीडी :: एमएमपीपी का व्यवहार ऑब्जेक्ट के लिए अनिर्धारित क्यों नहीं होगा, जो ट्रिविली को कॉपी करने योग्य नहीं हैं?

इस मामले में निर्माता की कॉपी क्यों नहीं की जाती है?

यहां छोटा कोड स्निपेट है:

class A { public: A(int value) : value_(value) { cout <<"Regular constructor" <<endl; } A(const A& other) : value_(other.value_) { cout <<"Copy constructor" <<endl; } private: int value_; }; int main() { A a = A(5); } 

मैंने मान लिया है कि उत्पादन "आरएफ़एस" के लिए "नियमित निर्माता" होगा और इसके बाद एलएचएस के लिए "प्रतिलिपि कन्स्ट्रक्टर" होगा। इसलिए मैं इस शैली से बचा था और हमेशा वर्ग के घोषित चर के रूप में A a(5); । लेकिन प्रतिलिपि निर्माता के ऊपर कोड में मुझे आश्चर्य करने के लिए कभी नहीं कहा जाता है (विज़ुअल सी ++ 2008)

क्या कोई यह जानता है कि यह व्यवहार कम्पाइलर अनुकूलन का परिणाम है, या कुछ दस्तावेज (और पोर्टेबल) सुविधा C ++ की है? धन्यवाद।

Solutions Collecting From Web of "इस मामले में निर्माता की कॉपी क्यों नहीं की जाती है?"

दूसरी टिप्पणी से: "तो डिफ़ॉल्ट रूप से मुझे इस पर भरोसा नहीं करना चाहिए (क्योंकि यह कंपाइलर पर निर्भर हो सकता है)"

नहीं, यह संकलक पर निर्भर नहीं है, व्यावहारिक रूप से वैसे भी। रेत के अनाज के लायक कोई भी कंपाइलर ए के निर्माण का समय बर्बाद नहीं करेगा, फिर इसे कॉपी करना होगा।

मानक में यह स्पष्ट रूप से कहता है कि यह T = x; लिए पूरी तरह स्वीकार्य है T = x; T(x); कहने के बराबर होना T(x); । (§12.8.15, पृष्ठ 211) T(T(x)) साथ ऐसा करना स्पष्ट रूप से बेमानी है, इसलिए यह आंतरिक T को हटा देता है

वांछित व्यवहार प्राप्त करने के लिए, आप कम्पाइलर को पहले ए का निर्माण करने के लिए मजबूर करते हैं:

 A a; // A is now a fully constructed object, // so it can't call constructors again: a = A(5); 

यहां आपके पास अस्थायी A(5) से कॉपी-आरंभीकरण है। कार्यान्वयन को C ++ मानक 12.2 / 2 के अनुसार यहां कॉलिंग कन्स्ट्रक्टर को छोड़ने की इजाजत है।

मैं इसे एक दूसरे सवाल का जवाब देने के लिए शोध कर रहा था जो एक धोखा के रूप में बंद हो गया था, ताकि काम को बर्बाद न होने देने के लिए मैं इसे एक का जवाब दे रहा हूं।

प्रपत्र A a = A(5) एक बयान को वैरिएबल के कॉपी-इनिशियलाइज़ेशन कहा जाता a । सी +11 11 मानक, 8.5 / 16 राज्यों:

चयनित फ़ंक्शन को इसके तर्क के रूप में प्रारंभिक अभिव्यक्ति के साथ कहा जाता है; अगर फ़ंक्शन एक कन्स्ट्रक्टर है, तो कॉल एक अस्थायी रूप से गंतव्य प्रकार के सीवी-अयोग्य संस्करण को प्रारंभ करता है। अस्थायी एक प्राइव्यू है कॉल के परिणाम (जो कन्स्ट्रक्टर केस के लिए अस्थायी है) का उपयोग इसके बाद के नियमों के अनुसार डायरेक्ट-इनिशियलाइज़ करने के लिए किया जाता है, उस ऑब्जेक्ट को कॉपी-इनिशियलाइज़ेशन का गंतव्य है। कुछ मामलों में, एक प्रत्यक्ष कार्यान्वयन को सीधे प्रत्यक्ष रूप से शुरू होने वाले वस्तु में मध्यवर्ती परिणाम का निर्माण करके इस प्रत्यक्ष-प्रारंभ में अंतर्निहित प्रतिलिपि को समाप्त करने की अनुमति है; 12.2, 12.8 देखें

इसका मतलब यह है कि कंपाइलर A(5) को संभालने के लिए उपयुक्त निर्माता को देखता है, एक अस्थायी बनाता है और उसमें अस्थायी रूप से प्रतियां बनाता है लेकिन किस परिस्थिति में प्रतिलिपि समाप्त हो सकती है?

देखते हैं कि 12.8 / 31 क्या कहते हैं:

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

[…]

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

यह सब ध्यान में रखते हुए, यहां अभिव्यक्ति के साथ क्या होता है A a = A(5) :

  1. संकलक प्रतिलिपि के साथ एक घोषणा देखता है- initialization
  2. A(int) निर्माता एक अस्थायी ऑब्जेक्ट को प्रारंभ करने के लिए चुना गया है
  3. चूंकि अस्थायी ऑब्जेक्ट किसी संदर्भ के लिए बाध्य नहीं है , और इसके पास A प्रकार के A को प्रति-आरंभीकरण अभिव्यक्ति में गंतव्य प्रकार के रूप में है, संकलक को सीधे ऑब्जेक्ट को a अस्थायी रूप से काम करने की अनुमति है
 A a = A(5); 

यह रेखा समतुल्य है

 A a(5); 

इसके समारोह-शैली की उपस्थिति के बावजूद, पहली पंक्ति में सिर्फ तर्क 5 का निर्माण होता a । कोई प्रतिलिपि या अस्थायी शामिल नहीं हैं। सी ++ मानक से, खंड 12.1.11:

एक कार्यात्मक संकेतन प्रकार रूपांतरण (5.2.3) इसका प्रकार के नए ऑब्जेक्ट बनाने के लिए इस्तेमाल किया जा सकता है। [नोट: वाक्यविन्यास कन्स्ट्रक्टर की एक स्पष्ट कॉल जैसा दिखता है -नोट नोट]