दिलचस्प पोस्ट
Android डिवाइस पर स्थानीय होस्ट कैसे ब्राउज़ करें? 3 अलग बराबर है क्या कारण java.lang.IncompatibleClassChangeError? कस्टम सूची फ़ील्ड क्लिक ईवेंट स्ट्रिंग को किसी तारीख को सी ++ में कनवर्ट करें आप अलग git मर्ज रणनीति का उपयोग कब करेंगे? टोमकैट में एक पृष्ठभूमि जावा प्रोग्राम चलाना jquery का उपयोग कर एक वेबसाइट का एक स्क्रीनशॉट उत्पन्न करना क्यों हैशमार्क को प्रारंभिक क्षमता दो की शक्ति होने की आवश्यकता है? बाहरी जेएस फाइल में एस्पनेट एमवीसी यूआरएल। एक्शन। पायथन में, आप ऑर्डर किए गए आदेश के रूप में YAML मैपिंग कैसे लोड कर सकते हैं? सूचना: अज्ञात: रेखा 0 पर अज्ञात में संख्यात्मक कुंजी लंघन देरी: CSS3 में होवर करें? पायथन स्रोत में यूटीएफ -8 एन्कोडिंग के साथ काम करना मोंगो समूह क्वेरी कैसे खेतों को रखने के लिए

प्रतिलिपि प्रारंभिक और प्रत्यक्ष प्रारंभ के बीच सी ++ में कोई अंतर है?

मान लीजिए मेरे पास यह फ़ंक्शन है:

void my_test() { A a1 = A_factory_func(); A a2(A_factory_func()); double b1 = 0.5; double b2(0.5); A c1; A c2 = A(); A c3(A()); } 

प्रत्येक समूहीकरण में, क्या ये बयान समान हैं? या क्या कुछ प्रारंभिकताओं में एक अतिरिक्त (संभवत: अनुकूलन योग्य) प्रतिलिपि है?

मैंने लोगों को दोनों चीजों को कहते देखा है कृपया सबूत के रूप में पाठ का हवाला देते इसके अलावा अन्य मामलों को भी जोड़ें

वेब के समाधान से एकत्रित समाधान "प्रतिलिपि प्रारंभिक और प्रत्यक्ष प्रारंभ के बीच सी ++ में कोई अंतर है?"

 A a1 = A_factory_func(); A a2(A_factory_func()); 

निर्भर करता है कि किस प्रकार A_factory_func() रिटर्न मुझे लगता है कि यह एक A देता है – फिर यह वही कर रहा है – सिवाय इसके कि जब प्रतिलिपि निर्माता स्पष्ट है, तो पहले एक असफल हो जायेगा। 8.6 / 14 पढ़िए

 double b1 = 0.5; double b2(0.5); 

यह वही कर रहा है क्योंकि यह एक अंतर्निहित प्रकार है (इसका मतलब यह नहीं कि क्लास प्रकार यहां है)। 8.6 / 14 पढ़िए

 A c1; A c2 = A(); A c3(A()); 

यह वही नहीं कर रहा है पहला डिफ़ॉल्ट -अनुमति देता है कि A एक गैर-पीओडी है, और कोई पीओडी ( 8.6 / 9 पढ़ा) के लिए कोई भी प्रारंभ नहीं करता है। दूसरी प्रतिलिपि प्रारंभ होती है: मान एक अस्थायी प्रारंभ करता है और फिर उस मूल्य की प्रतिलिपि को c2 ( 5.2.3 / 2 और 8.6 / 14 पढ़िए)। इस पाठ्यक्रम के लिए एक गैर स्पष्ट प्रतिलिपि कन्स्ट्रक्टर ( 8.6 / 14 और 12.3.1 / 3 और 13.3.1.3/1 पढ़ें ) की आवश्यकता होगी। तीसरा एक फ़ंक्शन c3 लिए एक फ़ंक्शन घोषणा बनाता है जो A देता है और जो किसी A (रीड 8.2 ) को लौटाने वाले फ़ंक्शन के लिए फ़ंक्शन पॉइंटर लेता है।


Initializations प्रत्यक्ष और कॉपी initialization में delving

हालांकि वे समान दिखते हैं और उन्हें ऐसा करना चाहिए, ये दो रूप निश्चित मामलों में उल्लेखनीय रूप से भिन्न होते हैं। आरंभ के दो रूप सीधे होते हैं और प्रतिलिपि कॉपी करते हैं:

 T t(x); T t = x; 

हम उनमें से प्रत्येक के लिए विशेषता का व्यवहार कर सकते हैं:

  • डायरेक्ट इनिशियलाइज़ेशन एक अतिभारित फ़ंक्शन के लिए फंक्शन कॉल की तरह व्यवहार करता है: इस मामले में, T के कन्स्ट्रक्टर ( explicit शामिल) हैं, और तर्क x ओवरलोड संकल्प सर्वश्रेष्ठ मिलान कन्स्ट्रक्टर को मिलेगा, और जब ज़रूरत पड़ती है, तो कोई भी निहित रूपांतरण आवश्यक होगा।
  • प्रारंभिक रूप से प्रतिलिपि बनाने से एक अंतर्निहित रूपांतरण अनुक्रम होता है: यह x को किसी वस्तु के प्रकार को परिवर्तित करने की कोशिश करता है। (यह तब उस ऑब्जेक्ट को शुरू करने वाले ऑब्जेक्ट में कॉपी कर सकता है, इसलिए एक कॉपी कन्स्ट्रक्टर भी आवश्यक है – लेकिन यह नीचे महत्वपूर्ण नहीं है)

जैसा कि आप देखते हैं, प्रारंभिक रूप से प्रतिलिपि किसी भी तरह से संभव अंतर्निहित रूपांतरणों के संबंध में प्रत्यक्ष प्रारंभ का एक हिस्सा है: प्रत्यक्ष प्रारंभ करने के लिए कॉल करने के लिए सभी कंस्ट्रक्टर्स उपलब्ध हैं, और इसके अलावा कोई भी अप्रत्यक्ष रूपान्तरण करने के लिए इसे तर्क प्रकारों से मिलान करने की आवश्यकता होती है, प्रारंभिकता की प्रतिलिपि बनाएँ सिर्फ एक अंतर्निहित रूपांतरण अनुक्रम सेट कर सकते हैं

मैंने कड़ी मेहनत की और explicit से explicit रचनाकारों के माध्यम से "स्पष्ट" का उपयोग किए बिना, उन प्रत्येक फ़ॉर्म के लिए अलग-अलग टेक्स्ट आउटपुट करने के लिए निम्न कोड प्राप्त किया।

 #include <iostream> struct B; struct A { operator B(); }; struct B { B() { } B(A const&) { std::cout << "<direct> "; } }; A::operator B() { std::cout << "<copy> "; return B(); } int main() { A a; B b1(a); // 1) B b2 = a; // 2) } // output: <direct> <copy> 

यह कैसे काम करता है, और इसका परिणाम यह परिणाम क्यों देता है?

  1. प्रत्यक्ष प्रारंभ

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

     B(A const&) 

    उस कन्स्ट्रक्टर को कॉल करने के लिए कोई रूपांतरण नहीं है, जो कम से कम एक उपयोगकर्ता परिभाषित रूपांतरण होता है (ध्यान दें कि यहां कोई कॉन्फ़ क्वालिफिकेशन रूपांतरण नहीं होता है)। और इसलिए प्रत्यक्ष प्रारंभिक इसे कॉल करेंगे

  2. प्रारंभिकता कॉपी करें

    जैसा कि ऊपर कहा गया है, आरंभिक की प्रतिलिपि एक रूपांतरण अनुक्रम का निर्माण करेगी जब a प्रकार B या उसमें से व्युत्पन्न नहीं होगा (जो यहां स्पष्ट रूप से मामला है)। तो यह रूपांतरण करने के तरीकों की खोज करेगा, और निम्नलिखित उम्मीदवारों को मिलेगा

     B(A const&) operator B(A&); 

    नोटिस कैसे मैं रूपांतरण फ़ंक्शन को दोबारा लिखता हूं: पैरामीटर प्रकार this पॉइंटर के प्रकार को दर्शाता है, जो गैर-कॉन्स्ट सदस्य फंक्शन में गैर-कॉन्स्ट है अब, हम इन उम्मीदवारों को x रूप में तर्क के रूप में कहते हैं। विजेता रूपांतरण फ़ंक्शन है: क्योंकि यदि हमारे पास दो उम्मीदवार कार्य दोनों हैं तो एक ही प्रकार के संदर्भ को स्वीकार करते हैं, तो कम कॉन्स्ट वर्जन जीत जाता है (यह वैसे भी, गैर-कॉन्स्ट सदस्य फंक्शन कॉल को पसंद करने वाला तंत्र गैर -कॉन्स्ट ऑब्जेक्ट्स)

    ध्यान दें कि यदि हम कनवर्ज़न फंक्शन को एक कॉन्स्ट सदस्य फंक्शन में बदलते हैं, तो रूपांतरण अस्पष्ट है (क्योंकि दोनों में पैरामीटर का A const& प्रकार A const& ): कम्यु कंपाइलर इसे ठीक से खारिज कर देता है, लेकिन जीसीसी इसे गैर-पेंडेंट मोड में स्वीकार करता है। -pedantic से स्विच करने से यह उचित अस्पष्टता चेतावनी को भी आउटपुट बनाती है, हालांकि।

मुझे उम्मीद है कि इससे स्पष्ट रूप से यह स्पष्ट करने में कुछ मदद मिलती है कि ये दो रूप कैसे भिन्न होते हैं!

असाइनमेंट प्रारंभिकरण से भिन्न है

निम्नलिखित दोनों पंक्तियों को प्रारंभ करना है । एक सिंगल कन्स्ट्रक्टर कॉल किया जाता है:

 A a1 = A_factory_func(); // calls copy constructor A a1(A_factory_func()); // calls copy constructor 

लेकिन यह इसके बराबर नहीं है:

 A a1; // calls default constructor a1 = A_factory_func(); // (assignment) calls operator = 

इस समय मेरे पास यह साबित करने के लिए कोई पाठ नहीं है लेकिन यह प्रयोग करना बहुत आसान है:

 #include <iostream> using namespace std; class A { public: A() { cout << "default constructor" << endl; } A(const A& x) { cout << "copy constructor" << endl; } const A& operator = (const A& x) { cout << "operator =" << endl; return *this; } }; int main() { A a; // default constructor A b(a); // copy constructor A c = a; // copy constructor c = b; // operator = return 0; } 

double b1 = 0.5; कन्स्ट्रक्टर की निहित कॉल है

double b2(0.5); स्पष्ट कॉल है

अंतर देखने के लिए निम्न कोड देखें:

 #include <iostream> class sss { public: explicit sss( int ) { std::cout << "int" << std::endl; }; sss( double ) { std::cout << "double" << std::endl; }; }; int main() { sss ddd( 7 ); // calls int constructor sss xxx = 7; // calls double constructor return 0; } 

अगर आपकी कक्षा में स्पष्ट और अंतर्निहित कॉल की तुलना में कोई स्पष्ट constuctors समान हैं।

प्रथम समूह: यह A_factory_func रिटर्न पर निर्भर करता है पहली पंक्ति प्रतिलिपि आरंभीकरण का एक उदाहरण है , दूसरी पंक्ति प्रत्यक्ष प्रारंभिकता है । यदि A_factory_func A ऑब्जेक्ट देता है तो वे समतुल्य हैं, वे दोनों A लिए प्रतिलिपि कन्स्ट्रक्टर को कॉल करते हैं, अन्यथा पहला संस्करण रिटर्न प्रकार A_factory_func या उपयुक्त A_factory_func लिए एक उपलब्ध रूपांतरण ऑपरेटर से टाइप A का एक A_factory_func , और फिर A_factory_func कॉल करता है इस अस्थायी से a1 1 के निर्माण के लिए कन्स्ट्रक्टर को कॉपी करें। दूसरा संस्करण एक उपयुक्त कन्स्ट्रक्टर को खोजने का प्रयास करता है जो कि A_factory_func रिटर्न देता है, या यह कुछ लेता है कि रिटर्न वैल्यू को परस्पर रूप से परिवर्तित किया जा सकता है

दूसरा समूह: ठीक उसी तर्क धारण करता है, सिवाय इसके कि प्रकार में निर्मित किसी भी विदेशी कन्स्ट्रक्टर नहीं हैं, इसलिए वे अभ्यास में समान हैं।

तीसरा समूह: c1 डिफ़ॉल्ट रूप से शुरू किया गया है, c2 प्रतिलिपि-प्रारंभिक मूल्य से अस्थायी प्रारंभिक है। c1 किसी सदस्य के पास पॉड-टाइप (या सदस्यों के सदस्य, आदि, आदि) आरंभिक नहीं हो सकते हैं यदि उपयोगकर्ता ने डिफ़ॉल्ट कन्स्ट्रक्टर (यदि कोई हो) उन्हें स्पष्ट रूप से प्रारंभ नहीं किया है c2 , यह इस बात पर निर्भर करता है कि क्या उपयोगकर्ता द्वारा प्रतिलिपि कन्स्ट्रक्टर की आपूर्ति की गई है और क्या वह उचित रूप से उन सदस्यों को आरम्भ करता है, लेकिन अस्थायी सदस्यों के सभी को आरम्भ किया जाएगा (शून्य-प्रारंभिक यदि अन्यथा स्पष्ट रूप से प्रारंभ नहीं किया गया है)। जैसा कि litb देखा, c3 एक जाल है यह वास्तव में एक फ़ंक्शन घोषणा है

टिप्पणी का:

[12.2 / 1] Temporaries of class type are created in various contexts: ... and in some initializations (8.5).

यानी, कॉपी-आरंभीकरण के लिए

[12.8 / 15] When certain criteria are met, an implementation is allowed to omit the copy construction of a class object ...

दूसरे शब्दों में, एक अच्छा संकलक प्रतिलिपि के लिए कोई प्रतिलिपि नहीं बनाएगा, जब इसे टाला जा सकता है; इसके बजाय यह केवल कन्स्ट्रक्टर को सीधे कॉल करेगा – यानी, सीधे- initialization की तरह।

दूसरे शब्दों में, कॉपी-इनिशियलाइजेशन ज्यादातर मामलों में डायरेक्ट-इनिशियलाइजेशन की तरह है, जहां रायबद्ध कोड लिखे गए हैं। चूंकि प्रत्यक्ष रूप से प्रारंभिक रूप से संभावित रूप से मनमाना (और इसलिए संभवतः अज्ञात) रूपांतरों का कारण बनता है, इसलिए जब भी संभव हो मैं प्रति-आरम्भिकरण का उपयोग करना पसंद करता हूं। (बोनस के साथ यह वास्तव में प्रारंभिक रूप दिखता है।) </ Opinion>

तकनीकी गृहिणी: [ऊपर से 12.2 / 1 प्रतिशत] Even when the creation of the temporary object is avoided (12.8), all the semantic restrictions must be respected as if the temporary object was created.

खुशी है कि मैं एक सी + + कंपाइलर नहीं लिख रहा हूँ

इस हिस्से के संबंध में जवाब देना:

ए सी 2 = ए (); ए सी 3 (ए ());

चूंकि ज्यादातर उत्तर पूर्व-सी ++ 11 हैं, मैं जोड़ रहा हूं जो सी + 11 11 को इसके बारे में कहना है:

एक सरल-प्रकार-विनिर्देशक (7.1.6.2) या टाइपनाम-स्पेसिफायर (14.6) एक कोष्ठकित अभिव्यक्ति सूची के बाद अभिव्यक्ति सूची के अनुसार निर्दिष्ट प्रकार के मान का निर्माण होता है। यदि अभिव्यक्ति की सूची एक एकल अभिव्यक्ति है, तो प्रकार रूपांतरण अभिव्यक्ति समतुल्य (अभिव्यक्ति में परिभाषित, और यदि परिभाषित की गई है) संगत कास्ट अभिव्यक्ति (5.4) में है। यदि निर्दिष्ट प्रकार एक वर्ग प्रकार है, तो वर्ग प्रकार पूरा हो जाएगा। यदि अभिव्यक्ति सूची में एक एकल मान से अधिक निर्दिष्ट होता है, तो प्रकार एक घोषित कन्स्ट्रक्टर (8.5, 12.1) के साथ एक वर्ग होगा, और अभिव्यक्ति टी (x1, x2, …) घोषणा के परिणाम के बराबर है (x1, x2, …); कुछ आविष्कृत अस्थायी चर टी के लिए, परिणामस्वरूप टी के मूल्य को एक प्राइव्यू के रूप में

तो अनुकूलन या नहीं वे मानक के अनुसार समतुल्य हैं। ध्यान दें कि यह अन्य उत्तरों के उल्लेख के अनुसार है। सिर्फ सही कहने के लिए मानक क्या सही है

इन मामलों में बहुत से एक ऑब्जेक्ट के कार्यान्वयन के अधीन हैं, इसलिए आपको एक ठोस जवाब देना मुश्किल है।

मामले पर विचार करें

 A a = 5; A a(5); 

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

संपादित करें: जैसा कि अन्य प्रतिक्रियाओं में उल्लिखित है, पहली पंक्ति वास्तव में प्रतिलिपि निर्माता कॉल करेगी। असाइनमेंट ऑपरेटर से संबंधित टिप्पणियों पर विचार करें, एक स्टैंड अकेले असाइन से संबंधित व्यवहार।

उस ने कहा, कैसे संकलक कोड का अनुकूलन करता है, उसके बाद उसका स्वयं का प्रभाव होगा अगर मेरे पास "=" ऑपरेटर कॉल करने वाला आरंभीकरण कन्स्ट्रक्टर है – यदि कंपाइलर कोई ऑप्टिमाइज़ेशन नहीं करता है, तो शीर्ष पंक्ति तब 2 छलांग प्रदर्शन करेगी, जैसा कि नीचे पंक्ति में एक के विपरीत है

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