2012-06-27 30 views
42

कुछ हद तक Why is copy constructor called instead of conversion constructor?प्रतिलिपि बनाने और प्रत्यक्ष प्रारंभिकता के पीछे क्या प्रेरणा है?

से संबंधित आरंभीकरण के लिए दोनों वाक्यविन्यास, प्रत्यक्ष कर रहे हैं और उसकी प्रतिलिपि प्रारंभ:

A a(b); 
A a = b; 

मैं उन्हें अलग परिभाषित व्यवहार होने के लिए प्रेरणा जानना चाहते हैं। प्रतिलिपि प्रारंभ करने के लिए, एक अतिरिक्त प्रति शामिल है, और मैं उस प्रतिलिपि के किसी भी उद्देश्य के बारे में नहीं सोच सकता। चूंकि यह एक अस्थायी प्रतिलिपि है, इसलिए इसे संभवतः अनुकूलित किया जा सकता है, इसलिए उपयोगकर्ता इस पर भरोसा नहीं कर सकता है - अतिरिक्त प्रतिलिपि अलग-अलग व्यवहार के लिए पर्याप्त कारण नहीं है। तो क्यों?

+0

मुझे एक संपादन में जाना पड़ा है। अगर मैंने कुछ भी उलझा लिया है, तो कृपया इसे वापस रखें :-) –

+0

@SteveJessop: टैग की गई भाषा वकील को टैग किया जाना चाहिए। –

+8

@ एएलएस: शायद, मुझे उस टैग का उद्देश्य पता नहीं है। सवाल का विचार है कि वास्तव में * कहता है कि spec * के बारे में ठीक बाल को विभाजित नहीं करना है, और यह वही है जो मैं भाषा-कानून के रूप में सोचता हूं। अगर इसे अनुमति है तो मैं इसे भाषा-डिजाइन टैग करना पसंद करूंगा। –

उत्तर

3

चूंकि यह एक अस्थायी से एक प्रति है, यह और शायद बाहर अनुकूलित किया जाएगा कर सकते हैं

कीवर्ड यहाँ शायद है। मानक प्रतिलिपि बनाने के लिए एक कंपाइलर की आवश्यकता नहीं है, लेकिन इसकी आवश्यकता नहीं है। अगर कुछ कंपेलरों ने इस कोड को (अनुकूलित) की अनुमति दी, लेकिन अन्य ने इसे अस्वीकार कर दिया (गैर अनुकूलित), यह बहुत असंगत होगा।

तो मानक इसे संभालने का एक सतत तरीका निर्धारित करता है - हर किसी को यह जांचना होगा कि कॉपी कन्स्ट्रक्टर पहुंच योग्य है, चाहे वे इसका उपयोग करें या नहीं।

विचार यह है कि सभी कंपाइलर्स को या तो कोड स्वीकार करना चाहिए या इसे अस्वीकार करना चाहिए। अन्यथा यह गैर पोर्टेबल होगा।


एक अन्य उदाहरण पर विचार

A a; 
B b; 

A a1 = a; 
A a2 = b; 

यह भी उतना ही a2 अनुमति देने के लिए असंगत होगा, लेकिन न करे a1 जब A रों कॉपी निर्माता निजी है।


हम भी मानक पाठ है कि एक वर्ग वस्तु आरंभ के दो तरीके अलग होने के लिए लक्षित कर रहे थे से देख सकते हैं (8.5/16):

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

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

एक अंतर यह है कि प्रत्यक्ष-प्रारंभिकता सीधे निर्मित वर्ग के रचनाकारों का उपयोग करती है। प्रति-प्रारंभिकरण के साथ, अन्य रूपांतरण कार्यों पर विचार किया जाता है और ये एक अस्थायी उत्पन्न कर सकते हैं जिसे प्रतिलिपि बनाना है।

+4

सच है, लेकिन वास्तव में सवाल को संबोधित नहीं करता है ... –

+0

लेकिन संभावित अतिरिक्त प्रति ** ** अंतर का कारण है। :-) –

+1

क्षमा करें, मैं अभी भी नहीं देखता कि कैसे। क्या आप उत्तर में थोड़ा और वर्णनात्मक हो सकते हैं? (डाउनवॉटर नहीं) –

4

केवल एक अटकलें, लेकिन मुझे डर है कि यह इस बात की पुष्टि कैसे यह वास्तव में था Bjarne Stroustrup बिना अधिक निश्चित होने के लिए मुश्किल हो जाएगा हूँ:

यह इस तरह से डिजाइन किया गया था क्योंकि यह मान लिया था इस तरह के व्यवहार प्रोग्रामर द्वारा की उम्मीद होगी , कि वह कॉपी की जाने की उम्मीद करेगा जब = चिह्न का उपयोग किया जाता है, और प्रत्यक्ष प्रारंभकर्ता वाक्यविन्यास के साथ नहीं किया जाता है।

मुझे लगता है कि संभावित प्रति एलिशन केवल मानक के बाद के संस्करणों में जोड़ा गया था, लेकिन मुझे यकीन नहीं है - यह कुछ है जो किसी को मानक इतिहास की जांच करके निश्चित रूप से बताने में सक्षम हो सकता है।

struct X 
{ 
    X(int); 
    X(const X&); 
}; 

int foo(X x){/*Do stuff*/ return 1; } 
X x(1); 
foo(x); 

compilers मैं परीक्षण किया है, foo को तर्क हमेशा की प्रतिलिपि बन पूर्ण अनुकूलन भी साथ चालू:

+0

ठीक है, लेकिन प्रोग्रामर * अतिरिक्त प्रति * क्यों चाहते हैं? ऐसा लगता है कि यह किसी भी उद्देश्य की सेवा नहीं करता है। –

+0

मैं सहमत हूं। यह मेरे लिए कोई समझ नहीं आता है, हालांकि यह एकमात्र संभावित स्पष्टीकरण है जिसे मैं कल्पना कर सकता हूं। मुझे लगता है कि केवल वे लोग जिन्होंने भाषा तैयार की है, वे अपने कारण बता सकते हैं। – Suma

+1

यूप। या कोई वास्तव में एक प्रतिलिपि चाहता था और कारणों का उपयोग कर सकते हैं। –

1

निम्नलिखित उदाहरण लें। इससे, हम उन प्रतियों को इकट्ठा कर सकते हैं सभी परिस्थितियों में समाप्त नहीं होंगे/नहीं।

अब भाषा डिज़ाइन परिप्रेक्ष्य से सोचने दें, उन सभी परिदृश्यों की कल्पना करें जिनके बारे में आपको सोचना होगा कि क्या आप एक प्रतिलिपि की आवश्यकता होने पर नियम बनाना चाहते हैं और जब यह नहीं है। यह बहुत मुश्किल होगा। इसके अलावा, भले ही आप नियमों के साथ आने में सक्षम थे, फिर भी वे समझने के लिए बहुत जटिल और लगभग असंभव होंगे। हालांकि, एक ही समय में, यदि आप हर जगह प्रतियां मजबूर करते हैं, तो यह बहुत अक्षम होगा। यही कारण है कि नियम वे हैं, आप नियमों को समझने के लिए समझते हैं कि अभी भी प्रतियों को मजबूर नहीं किया जा रहा है, अगर उन्हें टाला जा सके।

मुझे अब स्वीकार करना है, यह उत्तर सुमा के उत्तर के समान ही है। विचार यह है कि आप मौजूदा नियमों के साथ व्यवहार की उम्मीद कर सकते हैं, और लोगों के अनुसरण के लिए और कुछ भी कठिन होगा।

+0

foo मूल्य के आधार पर अपना तर्क लेता है, इसलिए यह स्पष्ट है कि इसमें एक प्रति शामिल होगी।मुझे नहीं लगता कि यह किसी भी तरह से प्रश्न के लिए प्रासंगिक है। – Tony

+0

@ टोनी: उदाहरण का पूरा बिंदु यह दिखाने के लिए है कि सभी प्रतियां समाप्त नहीं की जा सकती हैं। हालांकि कुछ परिस्थितियों में उन्हें elided किया जा सकता है, एक और सामान्य नियम बनाना आसान है, फिर प्रत्येक उपयोग के मामले के लिए व्यक्तिगत नियम बनाते हैं। –

0

तरह निर्मित प्रकार के प्रारंभ:

int i = 2; 

बहुत ही स्वाभाविक वाक्य रचना, भाग में ऐतिहासिक कारणों से (अपने उच्च विद्यालय के गणित याद) के कारण है। यह

int i(2); 

भले ही कुछ गणितज्ञ इस बिंदु पर बहस कर सकें। आखिरकार, एक समारोह (इस मामले में एक कन्स्ट्रक्टर) को कॉल करने और इसे एक तर्क देने में अप्राकृतिक कुछ भी नहीं है।

अंतर्निहित प्रकारों के लिए इन दो प्रकार के प्रारंभिक समान हैं। पूर्व मामले में कोई अतिरिक्त प्रति नहीं है। दोनों प्रकार के प्रारंभिक होने का कारण यही है और मूल रूप से उन्हें अलग-अलग व्यवहार करने का कोई विशिष्ट इरादा नहीं था।

हालांकि, उपयोगकर्ता परिभाषित प्रकार हैं और भाषा के बताए गए लक्ष्यों में से एक है कि उन्हें यथासंभव अंतर्निहित प्रकारों के रूप में व्यवहार करने की अनुमति दी जाए।

इस प्रकार, निर्माण की प्रतिलिपि बनाएँ (उदाहरण के लिए कुछ रूपांतरण फ़ंक्शन से इनपुट लेना) पहला वाक्यविन्यास का प्राकृतिक कार्यान्वयन है।

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