क्या हो रहा है ?
जब आप एक बनाते हैं Taxi
, तो आप एक सब Car
-जेक्ट भी बनाते हैं । और जब टैक्सी नष्ट हो जाती है, तो दोनों वस्तुएं नष्ट हो जाती हैं। जब आप कॉल test()
करते हैं तो आप Car
मूल्य से गुजरते हैं । तो एक दूसरा Car
कॉपी-कंस्ट्रक्ट हो जाता है और test()
बचे रहने पर नष्ट हो जाएगा । तो हमारे पास 3 विध्वंसक के लिए स्पष्टीकरण है: पहला और दो क्रम में अंतिम।
चौथा विध्वंसक (जो अनुक्रम में दूसरा है) अप्रत्याशित है और मैं अन्य संकलक के साथ पुन: पेश नहीं कर सका।
यह केवल एक अस्थायी तर्क के Car
लिए स्रोत के रूप में बनाया जा सकता है Car
। चूंकि यह Car
तर्क के रूप में सीधे मूल्य प्रदान करते समय नहीं होता है, मुझे संदेह है कि यह रूपांतरित करने के लिए Taxi
है Car
। यह अप्रत्याशित है, क्योंकि Car
प्रत्येक में पहले से ही एक सब -जेक्ट है Taxi
। इसलिए मुझे लगता है कि संकलक एक अस्थायी में एक अनावश्यक रूपांतरण करता है और वह कॉपी एलिसन नहीं करता है जो इस अस्थायी से बचा सकता था।
टिप्पणियों में दिया गया स्पष्टीकरण:
मेरे दावों को सत्यापित करने के लिए भाषा-वकील के मानक के संदर्भ में यहाँ स्पष्टीकरण:
- मैं जिस रूपांतरण की बात यहां कर रहा हूं, वह कंस्ट्रक्टर द्वारा रूपांतरण है
[class.conv.ctor]
, अर्थात किसी अन्य प्रकार (यहां टैक्सी) के तर्क के आधार पर एक वर्ग (यहां कार) की एक वस्तु का निर्माण।
- यह रूपांतरण इसके
Car
मूल्य को वापस करने के लिए एक अस्थायी वस्तु का उपयोग करता है । कंपाइलर को प्रति के अनुसार नकल बनाने की अनुमति दी जाएगी [class.copy.elision]/1.1
, क्योंकि यह एक अस्थायी निर्माण के बजाय, यह मान को सीधे पैरामीटर में लौटा सकता है।
- इसलिए यदि यह अस्थायी दुष्प्रभाव देता है, तो इसका कारण यह है कि संकलक स्पष्ट रूप से इस संभावित प्रति-प्रयोग का उपयोग नहीं करता है। यह गलत नहीं है, क्योंकि कॉपी एलिसेंस अनिवार्य नहीं है।
एसेसिस की प्रायोगिक पुष्टि
मैं अब उसी संकलक का उपयोग करके आपके मामले को पुन: पेश कर सकता हूं और यह पुष्टि करने के लिए एक प्रयोग आकर्षित करूंगा कि क्या हो रहा है।
ऊपर मेरी धारणा यह थी कि कंपाइलर ने सब- सब्जेक्ट Car(const &Taxi)
से कॉपी कंस्ट्रक्शन की जगह कंस्ट्रक्टर कन्वर्जन का इस्तेमाल करते हुए सबॉप्टिमल पैरामीटर पासिंग प्रोसेस Car
को चुना Taxi
।
तो मैंने कॉल करने की कोशिश की test()
लेकिन स्पष्ट रूप Taxi
से एक में कास्टिंग Car
।
मेरा पहला प्रयास स्थिति को सुधारने में सफल नहीं हुआ। संकलक ने अभी भी उप-निर्माण निर्माता रूपांतरण का उपयोग किया है:
test(static_cast<Car>(taxi)); // produces the same result with 4 destructor messages
मेरा दूसरा प्रयास सफल हुआ। यह कास्टिंग के रूप में अच्छी तरह से करता है, लेकिन संकलक को दृढ़ता से सुझाव देने Car
के लिए Taxi
और इस मूर्खतापूर्ण अस्थायी ऑब्जेक्ट को बनाए बिना उपयोग करने के लिए सूचक कास्टिंग का उपयोग करता है :
test(*static_cast<Car*>(&taxi)); // :-)
और आश्चर्य: यह उम्मीद के मुताबिक काम करता है, केवल 3 विनाश संदेश का उत्पादन :-)
समापन प्रयोग:
अंतिम प्रयोग में, मैंने रूपांतरण द्वारा एक कस्टम निर्माता प्रदान किया:
class Car {
...
Car(const Taxi& t); // not necessary but for experimental purpose
};
और इसे लागू करें *this = *static_cast<Car*>(&taxi);
। मूर्खतापूर्ण लगता है, लेकिन यह भी कोड उत्पन्न करता है जो केवल 3 विध्वंसक संदेश प्रदर्शित करेगा, इस प्रकार अनावश्यक अस्थायी वस्तु से बचा जाएगा।
इससे लगता है कि संकलक में एक बग हो सकता है जो इस व्यवहार का कारण बनता है। यह कुछ परिस्थितियों में बेस क्लास से प्रत्यक्ष कॉपी-निर्माण की संभावना नहीं है।
Taxi
Car