दिलचस्प पोस्ट
फाइल अपलोड के साथ ServletFileUpload के parseRequest? UIBezierPath से अंक की सूची कैसे प्राप्त करें? कैसे सीएसएस के साथ एक asp.net मेनू शैली कॉलम द्वारा वर्गीकृत पंक्तियों की संख्या कैसे प्राप्त करें? Jquery क्लिक घटना jquery का उपयोग गतिशील रूप से बनाया तत्व पर गोलीबारी नहीं MySQL के साथ यादृच्छिक पंक्तियों का चयन करना बैकस्पेस कुंजी को वापस नेविगेट करने से मैं कैसे रोक सकता हूं? एक NullReferenceException क्या है, और मैं इसे कैसे ठीक करूँ? कैसे एक डेटाफ्रेम पिवट करने के लिए कैसे एक UIView बाउंस एनीमेशन बनाने के लिए? एएसपी.नेट एमवीसी रूपों में चेकबॉक्स को कैसे नियंत्रित किया जाए? एक एंड्रॉइड गतिविधि से ऑब्जेक्ट को किसी अन्य का उपयोग करने के लिए कैसे भेजा जा सकता है? क्या PHP के filter_var FILTER_VALIDATE_EMAIL वास्तव में काम करता है? कैसे एक jQuery यूआई संवाद के अंदर IFRAME प्रदर्शित करने के लिए कौन सी SQL क्वेरी तेज है? सम्मिलित मानदंड पर या कहाँ क्लॉज पर फ़िल्टर करें?

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

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

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 ++ की है? धन्यवाद।

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

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

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

मानक में यह स्पष्ट रूप से कहता है कि यह 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) इसका प्रकार के नए ऑब्जेक्ट बनाने के लिए इस्तेमाल किया जा सकता है। [नोट: वाक्यविन्यास कन्स्ट्रक्टर की एक स्पष्ट कॉल जैसा दिखता है -नोट नोट]