"डिफ़ॉल्ट" का क्या मतलब है कि एक वर्ग 'फ़ंक्शन घोषणा के बाद?


221

मैंने defaultकक्षा में फ़ंक्शन घोषणाओं के बगल में उपयोग किया है। यह क्या करता है?

class C {
  C(const C&) = default;
  C(C&&) = default;
  C& operator=(const C&) & = default;
  C& operator=(C&&) & = default;
  virtual ~C() { }
};

26
असाइनमेंट ऑपरेटर घोषणाओं में "=" से पहले "और" क्या करता है?
दैनिक

जवाबों:


249

यह एक नया C ++ 11 फीचर है

इसका मतलब है कि आप उस फ़ंक्शन के संकलक-निर्मित संस्करण का उपयोग करना चाहते हैं, इसलिए आपको एक निकाय निर्दिष्ट करने की आवश्यकता नहीं है।

आप यह = deleteनिर्दिष्ट करने के लिए भी उपयोग कर सकते हैं कि आप संकलक को उस फ़ंक्शन को स्वचालित रूप से उत्पन्न नहीं करना चाहते हैं।

मूव कंस्ट्रक्टर और मूव असाइनमेंट ऑपरेटर्स की शुरूआत के साथ, कंस्ट्रक्टर्स, डिस्ट्रक्टर्स और असाइनमेंट ऑपरेटर्स के ऑटोमैटिक वर्जन जेनरेट होने के नियम काफी जटिल हो गए हैं। उपयोग करना = defaultऔर = deleteचीजों को आसान बनाना क्योंकि आपको नियमों को याद रखने की आवश्यकता नहीं है: आप बस कहते हैं कि आप क्या करना चाहते हैं।


17
= deleteअधिक मजबूत है: इसका मतलब है, उस फ़ंक्शन का उपयोग करना मना है, हालांकि यह अभी भी अधिभार संकल्प में भाग लेता है।
डेडुप्लिकेटर

2
लेकिन, अगर हम कंपाइलर जेनरेट डेफिनिशन का उपयोग करना चाहते हैं, तो क्या हमें "पहले इसे लिखने और फिर इसे डिफ़ॉल्ट रूप में असाइन करने" के बजाय उस फ़ंक्शन को लिखना नहीं छोड़ना चाहिए?
मयंक जिंदल

47

यह एक नया C ++ 0x फीचर है जो कंपाइलर को संबंधित कंस्ट्रक्टर या असाइनमेंट ऑपरेटर के डिफॉल्ट वर्जन को बनाने के लिए कहता है, यानी जो प्रत्येक सदस्य के लिए सिर्फ कॉपी या मूव एक्शन करता है। यह उपयोगी है क्योंकि मूव कंस्ट्रक्टर हमेशा डिफ़ॉल्ट रूप से उत्पन्न नहीं होता है (जैसे यदि आपके पास कस्टम डिस्ट्रक्टर है), कॉपी कंस्ट्रक्टर के विपरीत (और असाइनमेंट के लिए इसी तरह), लेकिन अगर लिखने के लिए कुछ भी गैर-तुच्छ नहीं है, तो बेहतर है कि इसे छोड़ दें। संकलक इसे हर बार अपने आप को बाहर निकालने की तुलना में संभालता है।

यह भी ध्यान दें कि यदि आप कोई अन्य गैर-डिफ़ॉल्ट कंस्ट्रक्टर प्रदान करते हैं तो एक डिफ़ॉल्ट निर्माणकर्ता उत्पन्न नहीं होगा। यदि आप अभी भी डिफ़ॉल्ट कंस्ट्रक्टर चाहते हैं, तो भी, आप इस सिंटैक्स का उपयोग कर सकते हैं कि कंपाइलर एक बना हो।

एक अन्य उपयोग के मामले के रूप में, ऐसी कई परिस्थितियाँ हैं जिनमें एक कॉपी कंस्ट्रक्टर को उत्पन्न नहीं किया जाएगा (जैसे कि यदि आप एक कस्टम चाल निर्माण प्रदान करते हैं)। यदि आप अभी भी डिफ़ॉल्ट संस्करण चाहते हैं, तो आप इस सिंटैक्स के साथ अनुरोध कर सकते हैं।

विवरण के लिए मानक 12.8 की धारा देखें।


5
हालांकि यह न केवल निर्माताओं और कार्य के लिए है, लेकिन यह भी करने के लिए लागू होता है operator new/new[], operator delete/delete[]और उनके भार के।
सेबेस्टियन मच

21

यह C ++ 11 में नया है, यहां देखें । यह काफी उपयोगी हो सकता है यदि आपने एक निर्माता को परिभाषित किया है, लेकिन दूसरों के लिए चूक का उपयोग करना चाहते हैं। प्री-सी ++ 11 आपको एक बार परिभाषित करने के बाद सभी कंस्ट्रक्टरों को परिभाषित करना होगा, भले ही वे चूक के बराबर हों।

यह भी ध्यान दें कि कुछ स्थितियों में उपयोगकर्ता को डिफ़ॉल्ट डिफाल्टर प्रदान करना असंभव है जो कि कंपाइलर डिफ़ॉल्ट और वैल्यू इनिशियलाइज़ेशन दोनों के तहत संश्लेषित किए गए समान व्यवहार करता है। defaultआपको वह व्यवहार वापस लाने की अनुमति देता है।


5
दूसरे पैराग्राफ के बारे में, क्या आप एक उदाहरण प्रदान कर सकते हैं?
जॉन स्मिथ

11

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


1

C ++ 17 N4659 मानक ड्राफ्ट

https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "स्पष्ट रूप से तयशुदा कार्य":

1 फार्म की एक कार्य परिभाषा:

attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;

को स्पष्ट रूप से डिफ़ॉल्ट परिभाषा कहा जाता है। एक फ़ंक्शन जिसे स्पष्ट रूप से डिफ़ॉल्ट किया जाएगा

  • (1.1) - एक विशेष सदस्य कार्य हो,

  • (1.2) - समान घोषित फ़ंक्शन प्रकार (संभवतः अलग-अलग रेफरी-क्वालीफायर को छोड़कर और कॉपी कंस्ट्रक्टर या कॉपी असाइनमेंट ऑपरेटर के मामले में, इसके अलावा, पैरामीटर प्रकार "नॉन-कॉस्ट टी के संदर्भ में" हो सकता है, जहां टी है) सदस्य फ़ंक्शन का नाम) जैसे कि इसे स्पष्ट रूप से घोषित किया गया हो, और

  • (१.३) - डिफ़ॉल्ट तर्क नहीं हैं।

2 स्पष्ट रूप से डिफॉल्ट किया गया फ़ंक्शन जिसे डिलीट के रूप में परिभाषित नहीं किया गया है, केवल तभी कॉन्स्ट्रेक्स घोषित किया जा सकता है, जब इसे स्पष्ट रूप से कॉन्स्टैक्स के रूप में घोषित किया गया हो। यदि किसी फ़ंक्शन को स्पष्ट रूप से इसकी पहली घोषणा पर डिफ़ॉल्ट रूप से परिभाषित किया गया है, तो यह निहित रूप से माना जाता है कि यदि अंतर्निहित घोषणा होगी।

3 यदि कोई फ़ंक्शन जो स्पष्ट रूप से डिफ़ॉल्ट रूप से डिफ़ॉल्ट है, एक noexcept-Specier के साथ घोषित किया गया है जो अंतर्निहित घोषणा (18.4) के समान अपवाद विनिर्देश का उत्पादन नहीं करता है, तो

  • (3.1) - यदि फ़ंक्शन अपनी पहली घोषणा पर स्पष्ट रूप से डिफ़ॉल्ट है, तो इसे हटाए जाने के रूप में परिभाषित किया गया है;

  • (३.२) - अन्यथा, कार्यक्रम बीमार है।

4 [उदाहरण:

struct S {
  constexpr S() = default;            // ill-formed: implicit S() is not constexpr
  S(int a = 0) = default;             // ill-formed: default argument
  void operator=(const S&) = default; // ill-formed: non-matching return type
  ~ S() noexcept(false) = default;    // deleted: exception specification does not match
private:
  int i;                              // OK: private copy constructor
  S(S&);
};
S::S(S&) = default;                   // OK: defines copy constructor

- अंतिम उदाहरण]

5 स्पष्ट रूप से डिफॉल्ट किए गए फ़ंक्शंस और निहित रूप से घोषित फ़ंक्शंस को सामूहिक रूप से डिफॉल्ट फ़ंक्शंस कहा जाता है, और कार्यान्वयन उनके लिए निहित परिभाषाएं प्रदान करेगा (15.1 15.4, 15.8), जिसका अर्थ हो सकता है कि उन्हें हटाए जाने के रूप में परिभाषित किया जाए। एक फ़ंक्शन उपयोगकर्ता-प्रदान किया गया है यदि यह उपयोगकर्ता-घोषित है और इसकी पहली घोषणा पर स्पष्ट रूप से डिफ़ॉल्ट या हटा नहीं है। एक उपयोगकर्ता द्वारा प्रदान किया गया स्पष्ट रूप से डिफ़ॉल्ट रूप से फ़ंक्शन (यानी, इसकी पहली घोषणा के बाद स्पष्ट रूप से डिफ़ॉल्ट) उस बिंदु पर परिभाषित किया गया है जहां यह स्पष्ट रूप से डिफ़ॉल्ट रूप से डिफ़ॉल्ट है; यदि इस तरह के फ़ंक्शन को स्पष्ट रूप से हटाए जाने के रूप में परिभाषित किया गया है, तो प्रोग्राम बीमार है। [नोट: किसी फ़ंक्शन को पहले घोषणा के बाद डिफ़ॉल्ट के रूप में घोषित करना एक कुशल कोड बेस के लिए एक स्थिर बाइनरी इंटरफ़ेस को सक्षम करते हुए कुशल निष्पादन और संक्षिप्त परिभाषा प्रदान कर सकता है। - अंतिम नोट]

6 [उदाहरण:

struct trivial {
  trivial() = default;
  trivial(const trivial&) = default;
  trivial(trivial&&) = default;
  trivial& operator=(const trivial&) = default;
  trivial& operator=(trivial&&) = default;
  ~ trivial() = default;
};
struct nontrivial1 {
  nontrivial1();
};
nontrivial1::nontrivial1() = default;       // not first declaration

- अंतिम उदाहरण]

फिर सवाल यह है कि कौन से कार्य स्पष्ट रूप से घोषित किए जा सकते हैं और ऐसा कब होता है, जो मैंने यहां बताया है:

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.