सदस्य निर्माता और विध्वंसक कॉल का आदेश


121

ओह सी ++ गुरु, मैं तुम्हारा ज्ञान चाहता हूँ। मेरे लिए मानक बोलें और बताएं कि क्या C ++ निम्नलिखित प्रोग्राम की गारंटी देता है:

#include <iostream>
using namespace std;

struct A
{
    A() { cout << "A::A" << endl; }
    ~A() { cout << "A::~" << endl; }
};

struct B
{
    B() { cout << "B::B" << endl; }
    ~B() { cout << "B::~" << endl; }
};

struct C
{
    C() { cout << "C::C" << endl; }
    ~C() { cout << "C::~" << endl; }
};

struct Aggregate
{
    A a;
    B b;
    C c;
};

int main()
{
    Aggregate a;
    return 0;
}

हमेशा उत्पादन करेंगे

A::A
B::B
C::C
C::~
B::~
A::~

दूसरे शब्दों में, क्या सदस्यों को घोषणा के क्रम से आरंभ करने और रिवर्स ऑर्डर में नष्ट होने की गारंटी है?


8
यह सूक्ष्म कीड़े का एक सामान्य रूप से सामान्य कारण है जब कक्षाएं बड़े और अस्पष्ट हो गए हैं। जब आपके पास 50 डेटा सदस्य होते हैं, और उनमें से बहुत सारी रचनाकार इंटेलाइज़र सूची में इनिशियलाइज़ हो जाती हैं, तो यह मानना ​​आसान हो सकता है कि कंस्ट्रक्शन का ऑर्डर इनिशियलाइज़र लिस्ट में ऑर्डर है। आखिरकार, कोड लेखकों ने ध्यान से सूची का आदेश दिया है ... क्या वे नहीं हैं?
फर्माक्विड

जवाबों:


140

दूसरे शब्दों में, क्या सदस्यों को घोषणा के क्रम से आरंभ करने और रिवर्स ऑर्डर में नष्ट होने की गारंटी है?

दोनों के लिए हाँ। 12.6.2 देखें

6 प्रारंभिक क्रम में निम्नलिखित क्रम में आगे बढ़ना होगा:

  • सबसे पहले, और केवल नीचे वर्णित के रूप में सबसे अधिक व्युत्पन्न वर्ग के निर्माता के लिए, वर्चुअल बेस कक्षाओं को उसी क्रम में आरम्भ किया जाएगा, जो बेस क्लासों के निर्देशित एसाइक्लिक ग्राफ के गहराई-पहले बाएं-से-दाएं ट्रैवर्सल पर दिखाई देते हैं, जहां "बाएं" -to-right ”व्युत्पन्न वर्ग आधार-निर्दिष्ट-सूची में आधार वर्ग के नामों की उपस्थिति का क्रम है।

  • फिर, प्रत्यक्ष आधार वर्गों को घोषणा के क्रम में आरम्भ किया जाएगा क्योंकि वे आधार-सूची-सूची (मेमरों के आदेशों की परवाह किए बिना) में दिखाई देते हैं।

  • फिर, गैर-स्थैतिक डेटा सदस्यों को उस क्रम में आरम्भ किया जाएगा, जो उन्हें वर्ग परिभाषा में घोषित किया गया था (फिर भी मेमर्स-इनिशियलाइजर्स के आदेश की परवाह किए बिना)।

  • अंत में, कंस्ट्रक्टर बॉडी के कंपाउंड-स्टेटमेंट को निष्पादित किया जाता है। [नोट: घोषणा आदेश यह सुनिश्चित करने के लिए अनिवार्य है कि आधार और सदस्य सबोबिज को आरंभीकरण के रिवर्स ऑर्डर में नष्ट कर दिया जाए। ध्यान दें]


2
अगर मुझे सही याद है, तो दोनों के लिए हाँ ... इसे एक स्टैक के रूप में सोचें। पहले धक्का दिया, आखिरी पोप किया गया। इसलिए, जब आपका पहला उदाहरण तात्कालिक होता है, तो स्टैक के क्रम में इसे मेमोरी में धकेल दिया जाता है। फिर, दूसरे को आगे बढ़ाया जाता है, तीसरे को दूसरे और आगे को। फिर, जब आपके उदाहरणों को नष्ट कर दिया जाता है, तो प्रोग्राम पहली बार नष्ट करने के लिए देखेगा, आखिरी जिसे धक्का दिया गया है। लेकिन मैं इसे इस तरह से गलत समझा सकता हूं, लेकिन यह वह तरीका है जिसे मैंने C / C ++ और ASM करते समय सीखा था।
विल मार्कॉइलर

29

हां, वे (गैर-स्थैतिक सदस्य हैं)। आरंभीकरण (निर्माण) के लिए 12.6.2 / 5 और विनाश के लिए 12.4 / 6 देखें।


10

हां, मानक गारंटी वाली वस्तुएं उनके द्वारा बनाए गए रिवर्स ऑर्डर में नष्ट हो जाती हैं। कारण यह है कि एक वस्तु दूसरे का उपयोग कर सकती है, इस प्रकार उस पर निर्भर है। विचार करें:

struct A { };

struct B {
 A &a;
 B(A& a) : a(a) { }
};

int main() {
    A a;
    B b(a);
}

यदि aइससे पहले विनाशकारी थे, bतो bएक अमान्य सदस्य संदर्भ होगा। वस्तुओं को उल्टे क्रम में नष्ट करके जिसमें वे बनाए गए थे हम सही विनाश की गारंटी देते हैं।


मैंने वास्तव में कभी नहीं माना कि यह नियम गुंजाइश सदस्यों के विनाश के आदेश पर भी लागू होता है!
यानो

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