1 पॉइंट द्वारा GN⁺ 2024-07-06 | 1 टिप्पणियां | WhatsApp पर शेयर करें

मुझे constructor नहीं चाहिए, लेकिन initialization ज़रूरी है

  • परिचय

    • C++ पहली बार सीखते समय, हमने यह सीखा कि compiler किन मामलों में default constructor उपलब्ध कराता है।
    • कुछ परिस्थितियों में object के initialize न होने के जोखिम पर विचार करने की ज़रूरत पड़ती है।
  • default initialization और value initialization

    • T t; default initialization करता है।
      • अगर T class type है और उसके पास default constructor है, तो वह चलाया जाता है।
      • अगर T array type है, तो उसके हर element का default initialization होता है।
      • अन्यथा, कुछ नहीं होता।
    • T t{}; value initialization करता है।
      • अगर T class type है, तो default constructor न होने पर, या user-provided/defaulted/deleted default constructor होने पर, default initialization किया जाता है।
      • अन्यथा, पहले 0 से initialize किया जाता है और फिर default initialization किया जाता है।
      • अगर T array type है, तो उसके हर element का value initialization होता है।
      • अन्यथा, 0 से initialize किया जाता है।
  • default constructor

    • यदि default constructor घोषित नहीं किया जाता, तो compiler उसे implicitly घोषित करता है।
    • implicitly घोषित default constructor में empty body और empty member initializer list होती है।
    • उदाहरण:
      struct T {
        int x;
        T() = default;
      };
      T t{};
      std::cout << t.x << std::endl; // output 0 है
      
  • implicitly defined default constructor

    • अगर default constructor implicitly घोषित हो या explicitly default के रूप में घोषित किया गया हो, तो compiler implicitly defined default constructor उपलब्ध कराता है।
    • उदाहरण:
      struct T {
        T();
      };
      T::T() = default;
      T t{};
      std::cout << t.x << std::endl; // output garbage value है
      
  • वे मामले जहाँ default constructor उपलब्ध नहीं कराया जा सकता

    • जब T में non-static reference member हो
    • जब T में ऐसा non-static member या non-abstract base class हो जिसे default construct या destruct नहीं किया जा सकता
    • जब T में default member initializer के बिना const non-static member हो
  • सही initialization

    • T t{}; list initialization करता है।
    • list initialization को direct-list-initialization और copy-list-initialization में बाँटा जाता है।
    • उदाहरण:
      struct S {
        int a;
        float b;
        char c;
      };
      S s{3, 4.0f, 'S'}; // constructor call नहीं होता
      
  • list initialization और aggregate initialization

    • aggregate initialization, list initialization का एक विशेष रूप है, जिसमें class या array के हर element को initializer list के हर element से copy-initialize किया जाता है।
    • उदाहरण:
      struct A {
        const int x;
      };
      A a{}; // a.x को 0 से initialize किया जाता है
      
  • parentheses का उपयोग करके initialization

    • parentheses के साथ initialization, direct non-list initialization करता है।
    • उदाहरण:
      struct T {
        const int& r;
      };
      T t(42); // t.r, 42 को refer करने वाला reference है
      
  • सारांश

    • initialization के नियम जटिल हैं, लेकिन constructor को सीधे लिखने पर अधिकांश समस्याओं से बचा जा सकता है।
    • compiler पर छोड़ने के बजाय, constructor खुद लिखना बेहतर है।

GN⁺ की राय

  • यह लेख C++ initialization rules की जटिलता को अच्छी तरह समझाता है।
  • C++ के initialization rules को समझना महत्वपूर्ण है, क्योंकि इसका code की stability और performance पर बड़ा असर पड़ता है।
  • initialization की समस्याओं से बचने का सबसे अच्छा तरीका है constructor को सीधे लिखना।
  • समान प्रकृति की दूसरी भाषा Rust है, जिसमें initialization rules अधिक स्पष्ट हैं।
  • नई तकनीक अपनाते समय, initialization rules जैसी बारीकियों को अच्छी तरह समझकर इस्तेमाल करना महत्वपूर्ण है।

1 टिप्पणियां

 
GN⁺ 2024-07-06
Hacker News राय
  • t के initialization का परिणाम 0 होगा

    • ऐसा इसलिए है क्योंकि t value-initialize होता है, और T में user-defined default constructor नहीं है, इसलिए object पहले 0-initialize होता है और फिर default constructor कॉल होता है
  • default constructor members को default-initialize करता है, जो value-initialization से अलग है

  • लगता है GCC भी इससे सहमत है

  • लेखक यह चूक गया कि वह वास्तव में x को value-initialize कर रहा है

    • इसलिए परिणाम उम्मीद से अलग आता है
  • नियमों की बारीकियाँ जटिल हैं और कभी-कभी अव्यावहारिक भी लगती हैं

    • लेकिन ज़्यादातर मामलों में अपेक्षित परिणाम मिल जाता है
  • default initialization को explicitly व्यक्त करना एक बड़ा सुधार होगा

    • क्योंकि value initialization सामान्य है, इसलिए जब default initialization चाहिए होता है तो comment लिखना पड़ता है
    • "std::array<int, 100> = void;" जैसी syntax बेहतर होगी
  • list initialization और aggregate initialization के बीच कड़ी यह है कि जब list initialization किसी aggregate पर लागू होती है, तो aggregate initialization किया जाता है

    • लेकिन अगर list में सिर्फ एक argument हो, तो direct initialization किया जाता है
  • एक element का मामला दो या उससे अधिक elements के मामले से अलग तरह से काम करता है

    • यह उस भाषा में होता है जहाँ parameter pack से struct बनाना लगातार आसान होता जा रहा है
  • आप अपना constructor लिख सकते हैं, और एक ही element दिए गए tuple या array को initialize कर सकते हैं

    • लेकिन special case में गलत constructor कॉल हो सकता है
  • जब C++11 initialization list पहली बार आई थी, तब इसे देखकर लगा था कि यह पागलपन है

  • "I Have No Mouth, and I Must Scream" (1967) का उल्लेख

  • T::T() = default; syntax का उपयोग

  • उम्मीद होती है कि output 0 होगा, लेकिन वास्तव में garbage value आएगी

    • कुछ चीज़ें परफ़ेक्ट नहीं हो सकतीं
  • यह library consumer को library के व्यवहार को बदलने की अनुमति देता है

  • अगर आप C++ की और जटिलता चाहते हैं, तो C++ FQA की सिफारिश की गई है

    • 15 साल बीत चुके हैं, लेकिन C++ पुराने features या behavior को लगभग कभी हटाता नहीं, इसलिए यह अब भी प्रासंगिक है
  • ब्लॉग थीम DEC युग के कंप्यूटरों से प्रेरित है, लेकिन साफ़-सुथरी और minimal है

    • ताज़गीभरी लगती है
  • इसे पढ़कर चक्कर आने लगता है

    • Java constructors और object initialization को समझने की कोशिश की याद आती है
  • Go और Rust में special constructors नहीं होते, इसलिए बहुत सी चीज़ें सरल हो जाती हैं

    • सोचने वाली बात है कि constructors का इस्तेमाल छोड़ने के बाद क्या किसी ने उन्हें मिस किया है
  • क्या कोई ऐसा C++ tool है जो सभी implicit behaviors दिखा सके

    • जैसे सभी added constructors, implicit copy constructor आदि
  • यह class के बारे में गलत जानकारी देता है

    • अगर आपने constructor declare किया है, तो default constructor नहीं मिलता, और default initialization compiler diagnostic के साथ fail हो जाता है
  • "T t;" का यह दावा कि यह "कुछ नहीं करता" गलत है

    • example code में T t; fail होता है
  • ब्लॉग header में DEC front panel है