C ++ में निम्नलिखित वाक्यांशों का क्या अर्थ है: शून्य-, डिफ़ॉल्ट- और मूल्य-आरंभीकरण?


190

C ++ में निम्नलिखित वाक्यांशों का क्या अर्थ है:

  • शून्य प्रारंभ,

  • डिफ़ॉल्ट-आरंभीकरण, और

  • मूल्य-आरंभीकरण

C ++ डेवलपर को उनके बारे में क्या पता होना चाहिए?



20
अभी और है! प्रारंभिकताओं की पूरी सूची: मूल्य, प्रत्यक्ष, प्रतिलिपि, सूची (C ++ 11 नया परिचय), समग्र, संदर्भ, शून्य, निरंतर और डिफ़ॉल्ट; en.cppreference.com/w/cpp/language/initialization उन सभी को उदाहरणों के साथ सूचीबद्ध करता है :)
किंवदंतियां 2

जवाबों:


65

एक बात का एहसास है कि C ++ 2003 मानक के साथ 'मूल्य-आरंभीकरण' नया है - यह मूल 1998 मानक में मौजूद नहीं है (मुझे लगता है कि यह एकमात्र अंतर हो सकता है जो एक स्पष्टीकरण से अधिक है)। मानक से सीधे परिभाषाओं के लिए किरिल वी। लयाडविंस्की का उत्तर देखें ।

इस operator newप्रकार के इनिशियलाइज़ेशन के अलग-अलग व्यवहार और जब वे किक करते हैं (और जब वे c ++ 98 से C ++ 03 से भिन्न होते हैं) पर विवरण के लिए इस पिछले उत्तर को देखें :

उत्तर का मुख्य बिंदु है:

कभी-कभी नए ऑपरेटर द्वारा दी गई मेमोरी को इनिशियलाइज़ किया जाएगा, और कभी-कभी यह इस बात पर निर्भर नहीं करेगा कि आप जिस प्रकार से नया कर रहे हैं वह एक POD है, या यदि यह एक वर्ग है जिसमें POD सदस्य हैं और एक कंपाइलर-जनरेट किए गए डिफ़ॉल्ट कंस्ट्रक्टर का उपयोग कर रहा है ।

  • C ++ 1998 में प्रारंभ के 2 प्रकार हैं: शून्य और डिफ़ॉल्ट
  • C ++ 2003 में एक 3 प्रकार के आरंभीकरण, मूल्य आरंभीकरण जोड़ा गया था।

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

निश्चित रूप से एक बात ज्ञात है कि MSVC C ++ 98 नियमों का पालन करता है, यहाँ तक कि VS 2008 (VC 9 या cl.exe संस्करण 15.x) में भी।

निम्न स्निपेट से पता चलता है कि MSVC और डिजिटल मंगल C ++ 98 नियमों का पालन करते हैं, जबकि GCC 3.4.5 और कोमू C3 03 नियमों का पालन करते हैं:

#include <cstdio>
#include <cstring>
#include <new>

struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

int main()
{
    char buf[sizeof(B)];
    std::memset( buf, 0x5a, sizeof( buf));

    // use placement new on the memset'ed buffer to make sure 
    //  if we see a zero result it's due to an explicit 
    //  value initialization
    B* pB = new(buf) B();   //C++98 rules - pB->m is uninitialized
                            //C++03 rules - pB->m is set to 0
    std::printf( "m  is %d\n", pB->m);
    return 0;
}

1
ऐसा नहीं है कि यह के लिए मायने रखता है int, लेकिन m()तीसरी पंक्ति मूल्य पर एम शुरू करता है। यदि आप को बदलना महत्वपूर्ण int m;है B m;। :)
जोहान्स स्काउब -

इस उदाहरण में राइट - Aऔर Cइसका उपयोग नहीं किया गया है (वे अन्य लिंक किए गए उत्तर से ले जाए गए हैं)। भले ही C ++ 98 और C ++ 03 का वर्णन करते समय Aऔर Cनिर्माण के दौरान अलग-अलग शब्दावली का उपयोग किया जाता है, लेकिन परिणाम दोनों मानकों में समान है। केवल struct Bअलग व्यवहार में परिणाम होता है।
माइकल बर्ट

1
मेरा मतलब है कि यदि आप C को बदलते हैं struct C { C() : m() {}; ~C(); B m; };, तो आपके पास m.m0. होगा। लेकिन अगर यह डिफ़ॉल्ट-इनिशियलाइज़ेशन mजैसा कि आप C ++ 03 कहते हैं, तो m.mC ++ 98 की तरह इनिशियलाइज़ नहीं किया जाएगा।
जोहान्स शाउब -

1
इस सुविधा के MSVC हैंडलिंग पर अतिरिक्त दिलचस्प टिप्पणियाँ: stackoverflow.com/questions/3931312/…
nobar

जब आप अपने प्रकार को स्थानीय चर के रूप में घोषित करते हैं, तो स्टैक पर कौन सा आरंभ होता है?
एंड्रे प्यूएल

88

C ++ 03 मानक 8.5 / 5:

टी प्रकार की एक वस्तु को शून्य-आरंभ करने का मतलब है:
- यदि टी एक अदिश प्रकार (3.9) है, तो वस्तु 0 में बदल जाती है (शून्य) टी में परिवर्तित हो जाती है;
- यदि टी एक गैर-यूनियन वर्ग प्रकार है, तो प्रत्येक गैर-डेटा डेटा सदस्य और प्रत्येक बेस-क्लास सबोबेज शून्य-प्रारंभिक है;
- यदि T एक यूनियन प्रकार है, तो ऑब्जेक्ट का पहला नामित डेटा सदस्य शून्य-प्रारंभिक है;
- यदि टी एक सरणी प्रकार है, तो प्रत्येक तत्व शून्य-आरंभीकृत है;
- यदि T एक संदर्भ प्रकार है, तो कोई आरंभ नहीं किया जाता है।

प्रकार टी के एक ऑब्जेक्ट को डिफ़ॉल्ट-इनिशियलाइज़ करने के लिए :
- यदि T एक गैर-POD वर्ग प्रकार (क्लॉज़ 9) है, तो T के लिए डिफॉल्ट कंस्ट्रक्टर को बुलाया जाता है (और टी को कोई डिफॉल्ट डिफॉल्ट कंस्ट्रक्टर होने पर इनिशियलाइज़ेशन को आधार बनाया जाता है);
- यदि T एक सरणी प्रकार है, तो प्रत्येक तत्व डिफ़ॉल्ट-आरंभिक है;
- अन्यथा, वस्तु शून्य-प्रारंभिक है।

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

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


18
यह C ++ 11 के लिए पुराना हो सकता है। cppreference.com बताता है कि डिफ़ॉल्ट आरंभीकरण सदस्यों को शून्य-आरंभ नहीं करता है (केवल मूल्य आरंभीकरण करता है)।
एलेक्सी शोलिक

3
@android एक महत्वपूर्ण बिंदु उठाता है, जिसे मैंने कहीं और उत्तर नहीं दिया है, इसलिए मैंने एक नया प्रश्न बनाया है। stackoverflow.com/questions/22233148/…
एड्रियन मैककार्थी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.