2011-08-25 14 views
8

पुस्तक जेनेरिक प्रोग्रामिंग और एसटीएल (चीनी संस्करण) में, यह कहते हैं:कन्स्ट्रक्टर या कॉपी कन्स्ट्रक्टर?

X x = X() प्रतिलिपि निर्माता कॉल करेंगे।

यह थोड़ा मुझे अजीब लगता है। और मैं इस परीक्षा

#include <iostream> 

class Test { 

public: 

    Test() { 
     std::cout << "This is ctor\n"; 
    } 

    Test(const Test&) { 
     std::cout << "This is copy-ctor\n"; 
    } 

}; 

int main(int argc, char** argv) 
{ 

    Test t = Test(); 
    return 0; 
} 

आउटपुट "यह सीटीओआर" है। ठीक है, अब मैं उलझन में हूँ, जो सही है?

उत्तर

9

Nomimally हाँ, एक अस्थायी डिफ़ॉल्ट-निर्माण किया है, और फिर प्रतिलिपि निर्माता अपनी वस्तु t में कॉपी करने के लिए शुरू हो जाती है।

हालाँकि, व्यवहार में नकल बाहर अनुकूलित किया जा सकता है — भले ही यह दुष्प्रभाव (कंसोल उत्पादन) है:

[n3290: 8.5/16]: [..] कुछ मामलों में, एक कार्यान्वयन अनुमति दी वस्तु प्रारंभ किया जा रहा में सीधे मध्यवर्ती परिणाम का निर्माण करके इस डायरेक्ट-प्रारंभ में निहित को कॉपी समाप्त करने के लिए; 12.2, 12.8 देखें।

और (एक ही खंड में दिए गए उदाहरण के साथ) का:

[n3290: 12.2/2]: [..] एक कार्यान्वयन एक अस्थायी में उपयोग कर सकते हैं (2) इसे पारित करने से पहले के निर्माण के लिए जो एक्स च() X 'का उपयोग करने के लिए रों कॉपी निर्माता; वैकल्पिक रूप से, X(2) अंतरिक्ष तर्क पकड़ इस्तेमाल में निर्माण किया जा सकता है। [..]

लेकिन प्रतिलिपि निर्माता अभी भी अस्तित्व में है, भले ही यह लागू नहीं किया जा सकता है।

वैसे भी, अगर आप अनुकूलन के साथ संकलन बंद कर दिया (या, जीसीसी के साथ, संभवतः -fno-elide-constructors), आप देखेंगे:

This is ctor 
This is copy-ctor 
+2

जीसीसी में, आपको '-फनो-एलिइड-कन्स्ट्रक्टर' का उपयोग करना पड़ सकता है, क्योंकि '-O0' भी elision को रोकता नहीं है, मुझे लगता है। –

+0

@Kerrek: धन्यवाद! –

+0

प्रतिलिपि elided जा सकती है, तब भी जब यह * तुच्छ * नहीं है, प्रतिलिपि स्थानीय चर के स्थान पर अस्थायी निर्माण करके elided है। ऑब्जेक्ट या प्रतिलिपि की जटिलता उस अनुकूलन के लिए अप्रासंगिक है। –

4

सिद्धांत रूप में, X x = X() एक अस्थायी वस्तु बनाने के लिए डिफ़ॉल्ट निर्माता फोन करेगा, और कॉपी कन्स्ट्रक्टर का उपयोग करके x में कॉपी करें।

प्रैक्टिस में, कंपाइलर्स को कॉपी निर्माण भाग और डिफ़ॉल्ट-निर्माण x सीधे छोड़ने की अनुमति है (जो डेविड अपनी टिप्पणी में बताते हैं, फिर भी कॉपी कन्स्ट्रक्टर को सिंटैक्टिक रूप से सुलभ होने की आवश्यकता होती है)। अधिकांश कंपाइलर कम से कम अनुकूलन सक्षम होने पर ऐसा करते हैं।

+4

यह ध्यान रखना महत्वपूर्ण है कि कॉपी कन्स्ट्रक्टर उपलब्ध होना चाहिए, भले ही प्रतिलिपि बनाई गई हो। यही है, अगर यह सुलभ नहीं है तो संकलक एक त्रुटि के साथ लाइन को अस्वीकार कर देगा। –

+0

@ डेविड: आप सही हैं। मैंने इसे अपने जवाब में शामिल किया है। इस बात की जानकारी देने के लिए धन्यवाद। – sbi

2

यह एक मामले में जहां Return Value Optimisation(RVO) का एक रूप (इसके अलावा Copy Elision के रूप में जाना जाता है) अनुकूलन पर एक बहुत मदद कर सकते हैं है। लिंक किए गए विकिपीडिया पेज में क्या हो रहा है इसका एक बहुत अच्छा स्पष्टीकरण है।

+3

मुझे नहीं लगता कि यह कड़ाई से सही है। यहां कोई फ़ंक्शन कॉल नहीं है जो 'एक्स' लौटाता है (याद रखें कि रचनाकारों के पास वापसी मान नहीं हैं)। यह प्रतिलिपि elision है, जो एक संबंधित, लेकिन विशिष्ट अवधारणा है। –

+0

मैं सहमत हूं। यह सख्ती से आरवीओ नहीं है (हालांकि यह संबंधित है)। –

+0

@Tomak: यह भी पूरी तरह से गलत नहीं है। यह * उस तरह * अनुकूलन का एक प्रकार है। डाउनवोट को संतुलित करने के लिए +1। –