2016-02-04 3 views
5

सी ++ 11 में, कोई स्पष्ट रूप से एक विशेष सदस्य फ़ंक्शन को डिफ़ॉल्ट रूप से डिफ़ॉल्ट कर सकता है, अगर इसकी अंतर्निहित पीढ़ी स्वचालित रूप से रोका गया हो।स्पष्ट रूप से डिफॉल्ट किए गए विशेष सदस्य फ़ंक्शन पीढ़ी को लागू करना

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

struct A 
{ 
    A()   = default; 
    A (const A&) = default; 
    A (A&&)  = delete; // Move constructor is deleted here 
}; 

struct B 
{ 
    B()   = default; 
    B (const B&) = default; 
    B (B&&)  = default; // Move constructor is defaulted here 

    A a; 
}; 

बी में कदम निर्माता, संकलक द्वारा उत्पन्न किया जा नहीं होगा क्योंकि ऐसा करने से एक संकलन त्रुटि उत्पन्न होगी (एक के कदम निर्माता हटा दी जाती है):

इस परिदृश्य पर विचार करें। स्पष्ट रूप से ए के कन्स्ट्रक्टर को हटाने के बिना, बी के चालक कन्स्ट्रक्टर को अपेक्षित के रूप में उत्पन्न किया जाएगा (इसे कॉपी करने के बजाए ए कॉपी करना)।

इस तरह के एक वस्तु को स्थानांतरित करने के लिए चुपचाप बजाय प्रतिलिपि निर्माता का उपयोग करेगा प्रयास कर रहा है:

B b; 
B b2 (std::move(b)); // Will call B's copy constructor 

वहाँ या तो समारोह पैदा करने में संकलक मजबूर या एक संकलन त्रुटि अगर यह नहीं कर सकते हैं जारी करने के लिए कोई तरीका है? इस गारंटी के बिना, डिफ़ॉल्ट हटाए गए कन्स्ट्रक्टरों पर भरोसा करना मुश्किल है, यदि एक हटाया गया कन्स्ट्रक्टर पूरे ऑब्जेक्ट पदानुक्रमों के लिए स्थानांतरित कर सकता है।

+0

क्या आपको नहीं पता होना चाहिए कि आपके द्वारा शामिल किए गए सदस्य चलने योग्य हैं या नहीं? – NathanOliver

+2

कक्षा को मूल रूप से लागू होने पर वे चलने योग्य हो सकते हैं, हालांकि, यदि कोई और सदस्य बाद में जोड़े जाते हैं, तो चलने योग्य आवश्यकता को अनदेखा किया जा सकता है (विशेष रूप से यदि वे किसी और द्वारा जोड़े जाते हैं)। –

+1

यह ध्यान दिया जाना चाहिए कि एक प्रकार जो इसके चालक कन्स्ट्रक्टर को हटा देता है लेकिन * नहीं * इसकी प्रतिलिपि निर्माता बहुत ही विचित्र है ... विचित्र। ऐसा करके हासिल करने के लिए बिल्कुल कुछ भी नहीं है। तो इस मामले को अनदेखा करना सबसे अच्छा हो सकता है, किसी भी कारण से बेवकूफ कुछ करने का परिणाम होने पर विचार करना। –

उत्तर

3

A जैसे प्रकारों का पता लगाने का एक तरीका है। लेकिन केवल तभी टाइप चालक कन्स्ट्रक्टर को हटा देता है। यदि चालक कन्स्ट्रक्टर को हटाए जाने के रूप में पूरी तरह से जेनरेट किया गया है, तो यह ओवरलोड रिज़ॉल्यूशन में भाग नहीं लेगा। यही कारण है कि B चल रहा है भले ही A नहीं है। Bdefault एस चालक कन्स्ट्रक्टर, जिसका अर्थ है कि यह पूरी तरह से हटा दिया जाता है, इसलिए प्रतिलिपि होती है।

B इसलिए रचनात्मक हो जाता है। हालांकि, A नहीं है। तो यह इस बात का एक सरल बात है:

struct B 
{ 
    static_assert(is_move_constructible<A>::value, "Oops..."); 

    B()   = default; 
    B (const B&) = default; 
    B (B&&)  = default; // Move constructor is defaulted here 

    A a; 
}; 

अब, कोई सामान्य किसी भी प्रकार जो आप चाहते करने के लिए कॉपी-केवल प्रकार होते हैं पैदा करने के लिए जिस तरह से। यही है, आपको व्यक्तिगत रूप से प्रत्येक प्रकार पर स्थिर जोर देना होगा; आप B को स्थानांतरित करने के प्रयासों को विफल करने के लिए डिफ़ॉल्ट चालक कन्स्ट्रक्टर में कुछ वाक्यविन्यास नहीं डाल सकते हैं।

इसका कारण पीछे की संगतता के साथ भाग लेना है। सभी पूर्व-सी ++ 11 कोड के बारे में सोचें जो उपयोगकर्ता द्वारा परिभाषित कॉपी कन्स्ट्रक्टर घोषित करते हैं। सी ++ 11 में कन्स्ट्रक्टर पीढ़ी के कदमों के नियमों के अनुसार, उनमें से सभी ने चालकों को हटा दिया होगा। जिसका अर्थ है कि T t = FuncReturningTByValue(); फॉर्म का कोई भी कोड असफल हो जाएगा, भले ही यह कॉपी कन्स्ट्रक्टर को कॉल करके सी ++ 98/03 में ठीक काम करता है। तो चालक द्वारा प्रतिलिपि उत्पन्न नहीं किया जा सका अगर चालक प्रतिलिपि जारी करने के बजाय इन प्रतिलिपि बनाकर इस प्रतिलिपि बनाकर काम किया।

लेकिन = default का अर्थ है "जो भी आप सामान्य रूप से करेंगे" करते हैं, इसमें यह विशेष अधिभार रिज़ॉल्यूशन व्यवहार भी शामिल है जो स्पष्ट रूप से हटाए गए चालक कन्स्ट्रक्टर को अनदेखा करता है।

संबंधित मुद्दे

 संबंधित मुद्दे