2013-05-23 10 views
38

मैं समझता हूं कि ज्यादातर मामलों में, हमें एक विनाशक को स्पष्ट रूप से कॉल नहीं करना चाहिए। हालांकि, मैं सी ++ 11 स्टैंडर्ड N3485 धारा 13.4.5 खाका तर्कों से एक उदाहरण देखा:कॉलर विनाशक को स्पष्ट रूप से

एक प्रकार है कि एक वर्ग टेम्पलेट विशेषज्ञता स्पष्ट टेम्पलेट निर्दिष्ट कर सकता है है है कि एक वस्तु के लिए एक स्पष्ट नाशक कॉल -arguments। उदाहरण:

template<class T> struct A { 
    ~A(); 
}; 

void f(A<int>* p, A<int>* q) { 
    p->A<int>::~A();  // OK: destructor call 
    q->A<int>::~A<int>(); // OK: destructor call 
} 

मुझे ऐसा लगता है कि हम इस मामले में स्पष्ट रूप से नाशक कॉल कर सकते हैं, तुम मेरी बात क्यों समझा सकता है? इस उदाहरण में उन विनाशक कॉल का मतलब क्या है? वे उचित क्यों हैं?

एक और सवाल:

क्या मामलों है कि हम विनाशकर्ता स्पष्ट अलावा कॉल कर सकते हैं जब हम placement delete कार्यान्वित कर रहे हैं कर रहे हैं?

धन्यवाद।

संपादित करें: मुझे C++ FAQ से मिला है कि हमें स्थानीय चर पर एक विनाशक को स्पष्ट रूप से कॉल नहीं करना चाहिए।

+4

संदर्भित पोस्ट एक स्थानीय चर पर स्पष्ट रूप से एक विनाशक को बुलाए जाने के बारे में है, जिसका विनाशक इसके दायरे के अंत में फिर से बुलाया जाता है। –

+0

+1 मैंने अपने कोड में कुछ समान बकवास किया है, जिससे विनाशक को मेरी वस्तु को नष्ट करने के लिए स्पष्ट रूप से बुलाया गया है (या यह काम करने लगता है)। लेकिन मैंने इसे प्रबंधित प्रकारों पर किया है। जवाब देखने के लिए दिलचस्प होगा –

+0

@ एंडी थॉमस-क्रैमर मैं समझता हूं, मेरा मतलब क्या है जो उत्तर से स्पष्टीकरण है जो स्पष्ट विनाशक कॉल के बारे में मानक उद्धृत करता है। क्या मेरी पोस्ट भ्रामक है? अगर यह एक समस्या है तो मैं इसे पुन: पेश करने की कोशिश करूंगा। – taocp

उत्तर

30

ऐसा लगता है कि हम इस मामले में स्पष्ट रूप से विनाशक को बुला सकते हैं, क्या आप मुझे समझा सकते हैं क्यों?

क्या आपका मतलब है हम क्यों कर सकते हैं? क्योंकि भाषा किसी ऑब्जेक्ट पर स्पष्ट विनाशक कॉल की अनुमति देती है। जैसा कि आप कहते हैं, यह आमतौर पर अपरिभाषित व्यवहार देता है क्योंकि अधिकांश वस्तुओं को किसी अन्य तरीके से नष्ट कर दिया जाएगा, और यह दो बार नष्ट करने के लिए अपरिभाषित व्यवहार है (या आमतौर पर विनाश के बाद इसे एक्सेस करने के लिए)। लेकिन इसका मतलब यह है कि आपको यह नहीं करना चाहिए, न कि भाषा आपको इसे करने से रोकती है।

या क्या आपका मतलब है कि हम क्यों चाहते हैं? क्योंकि इस तरह आप प्लेसमेंट द्वारा बनाई गई वस्तु को नष्ट करते हैं।

इस विनाशक कॉल का मतलब इस उदाहरण में क्या है?

वे दोनों एक ही बात मतलब है, और p->~A() के बराबर हैं; वे वस्तु के विनाशक को बुलाते हैं। उदाहरण यह दर्शाता है कि यदि आप चाहते हैं तो आप यहां टेम्पलेट तर्क प्रदान कर सकते हैं। मुझे यकीन नहीं है कि आप क्यों चाहते हैं।

प्लेसमेंट हटाने के अलावा हम कौन से मामले विनाशकों को स्पष्ट रूप से कॉल कर सकते हैं?

मुझे लगता है कि है कि आप एक छोटी सी नाशक (एक है कि कुछ भी नहीं है) जब चाहें तब कॉल करने के लिए अनुमति हो; लेकिन कोई बात नहीं है। मुझे लगता है कि नियुक्ति के साथ बनाई गई कुछ चीज़ों को नष्ट करना ही ऐसा करने का एकमात्र वैध कारण है।

+0

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

+1

+1। इसके अलावा, आप छोटे विनाशकों के बारे में सही हैं, क्योंकि §3.8/1 परिभाषित करता है कि एक विनाशकारी विनाशक के साथ किसी ऑब्जेक्ट का जीवनकाल समाप्त नहीं होता है जब विनाशक कहलाता है, लेकिन जब उस ऑब्जेक्ट के लिए संग्रहण का पुन: उपयोग किया जाता है या –

+0

@AndyProwl जारी किया जाता है मेरी टिप्पणी को बंद करें। :) –

21

ऐसा लगता है कि हम इस मामले में स्पष्ट रूप से विनाशक को बुला सकते हैं, क्या आप मुझे समझा सकते हैं क्यों?

क्योंकि जब भी आप चाहें तो किसी भी वस्तु के विनाशक को आमंत्रित करने में सक्षम होने के लिए भाषा की अनुमति है (मान लीजिए कि आपके पास पहुंच है, उदाहरण के लिए यह एक निजी विनाशक नहीं है)।

क्या उन नाशक कॉल इस उदाहरण में क्या मतलब है?

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

वे उचित क्यों हैं?

कभी-कभी आपको अपनी याददाश्त जारी किए बिना वस्तुओं को नष्ट करने की आवश्यकता होती है। इस प्रकार/किसी भी, विभिन्न स्क्रिप्ट बंधन और प्रतिबिंब प्रणाली, कुछ सिंगलटन कार्यान्वयन की तरह कक्षा का एक बहुत में होता है, आदि

उदाहरण के लिए, आप std::aligned_storage उपयोग कर सकते हैं एक वस्तु के लिए एक बफर आवंटित करने के लिए और उसके बाद नियुक्ति नए का उपयोग निर्माण करने के लिए के लिए उस बफर में एक वस्तु। आप इस ऑब्जेक्ट पर delete पर कॉल नहीं कर सकते हैं क्योंकि इससे दोनों विनाशक का आह्वान करेंगे और स्मृति का समर्थन करने की कोशिश करेंगे। आप स्पष्ट रूप से इस मामले में विनाशक को ऑब्जेक्ट को सही तरीके से नष्ट करने के लिए आमंत्रित करते हैं।

मामलों है कि हम स्पष्ट रूप से नियुक्ति के अलावा हटाना विनाशकर्ता कॉल कर सकते हैं क्या हैं?

वहाँ वास्तव में इस तरह के एक नया स्थान (और delete के लिए किसी भी कॉल करने के लिए इसी ऑपरेटर के अलावा अन्य 'को हटाना प्लेसमेंट' के रूप में बात, परोक्ष उन संकलक में विफल रहा है निर्माण के लिए आह्वान को छोड़कर नाशक लागू करेगा नहीं है, उदाहरण के लिए अपने 'प्लेसमेंट को हटा 'धारणा)।

एक उदाहरण मैंने ऊपर दिया। एक और उदाहरण std::vector है। आप सदस्य कार्यों को pop_back() पर कॉल कर सकते हैं। इसे वेक्टर में अंतिम तत्व को नष्ट करने की आवश्यकता है लेकिन यह delete का उपयोग नहीं कर सकता है क्योंकि ऑब्जेक्ट का समर्थन करने वाली मेमोरी एक बड़े बफर का हिस्सा है जिसे अलग से प्रबंधित किया जाना चाहिए। यह कई अन्य कंटेनरों के लिए भी जाता है, जैसे ओपन-एड्रेसिंग हैश टेबल, deque, और इसी तरह। विनाशक को स्पष्ट रूप से आमंत्रित करने के लिए यह एक उदाहरण है जहां आप template typename का उपयोग करना चाहते हैं।

यह एक विशेषता है कि पुस्तकालय के उपयोगकर्ता को शायद ही कभी आवश्यकता होती है लेकिन एसटीएल या यहां तक ​​कि कुछ एप्लिकेशन ढांचे जैसे निम्न स्तर की लाइब्रेरी के कार्यान्वयन को यहां और वहां उपयोग करने की आवश्यकता होगी।

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