2010-09-29 2 views
26

के साथ किसी ऑब्जेक्ट को हटाने से पहले पूर्ण जांच कोड समीक्षा टिप्पणियों में से एक के रूप में सामने आई।एक अधिभारित हटाए गए

क्या किसी ऑब्जेक्ट के लिए डिलीट करने से पहले एनयूएलएल की जांच करना अच्छा विचार है?

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

+7

हा। स्पष्ट रूप से कोई भी (मुझे शामिल नहीं) जवाब देने से पहले पूरी तरह से प्रश्न पढ़ें। –

+3

@ कोनराड - :) हमें बताता है कि कितने उत्सुक लोग मदद कर रहे हैं। यह एक महान साइट है। इसे प्यार करना! –

+0

संबंधित देखें: http://stackoverflow.com/questions/1265666/reason-why-not-to-have-a-delete-macro-for-c – moala

उत्तर

35

नहीं, शून्य के लिए जांच न करें। मानक कहता है कि delete (T*)0; मान्य है। यह आपके कोड को बिना किसी लाभ के जटिल करेगा। यदि operator delete अधिभारित है तो ऑपरेटर के कार्यान्वयन में शून्य की जांच करना बेहतर है। बस कोड लाइनों और बग बचाता है।

संपादित करें: यह उत्तर स्वीकार किया गया था और अभी तक, मेरी राय में, यह बहुत जानकारीपूर्ण नहीं था। यहां सभी उत्तरों में एक गायब टुकड़ा है, और, विवेक के लिए, मुझे यह अंतिम टुकड़ा यहां जोड़ने दें।

मानक वास्तव में [basic.stc.dynamic] में कहते हैं, कम से कम के बाद से सी ++ 03:

किसी भी आवंटन और/या आवंटन रद्द करने कार्यों एक सी में परिभाषित ++ कार्यक्रम, में डिफ़ॉल्ट संस्करणों सहित पुस्तकालय, 3.7.4.1 और 3.7.4.2 में निर्दिष्ट अर्थशास्त्र के अनुरूप होगा।

जहां संदर्भित अनुभाग, साथ ही साथ अन्य उत्तरों में सूचीबद्ध मानक में कुछ अन्य स्थान कहते हैं कि एक शून्य सूचक पास करने के अर्थशास्त्र एक नो-ऑप हैं।

+1

तो इसका मतलब है ओवरलोडेड 'ऑपरेटर डिलीट' की जिम्मेदारी ऑपरेटर के कार्यान्वयन में मानक झूठ के अनुरूप है? यानी अगर यह न्यूल की जांच नहीं करता है तो यह मानक के अनुरूप नहीं है? – Naveen

+0

@Naveen - यही सवाल है कि मैं जवाब देने का प्रयास कर रहा हूं, इसे सही शब्दों के साथ लाने के लिए धन्यवाद! –

+2

@Naveen @Als: हाँ कमजोर भावना में। शब्द "अनुरूप" शब्द की मजबूत भावना में नहीं। यदि आप ऑपरेटर डिलीट को कार्यान्वित करते हैं जो कि अभी भी अनुरूप नहीं है, तो यह अभी भी अनुरूप है (उदाहरण के लिए यह सिर्फ 'cout << पता <<' \ n'' प्रिंट करता है)। लेकिन अगर यह अपरिभाषित व्यवहार लाता है तो यह आपके 'ऑपरेटर डिलीट' कार्यान्वयन में एक बग है। – ybungalobill

19

मैं कहूंगा कि यह सुनिश्चित करने का एक और कारण है कि यदि आप operator delete अधिभारित करते हैं, तो आपको हमेशा NULL के लिए जांच करनी चाहिए, अन्यथा आप अर्थशास्त्र को तोड़ रहे हैं।

7

क्या किसी ऑब्जेक्ट के लिए डिलीट करने से पहले एनयूएलएल की जांच करना अच्छा विचार है?

नहीं!

int *p = NULL; 
delete p ; //no effect 

स्टैंडर्ड कहते हैं [धारा 5.3.5/2]

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

इसके अलावा धारा 18.4.1.1/13

void operator delete(void* ptr) throw();

में void operator delete(void* ptr, const std::nothrow_t&) throw();

डिफ़ॉल्ट व्यवहार:

- ptr की एक शून्य मान के लिए, कुछ भी नहीं है।

- पीआरटी का कोई भी अन्य मूल्य डिफ़ॉल्ट ऑपरेटर को कॉल द्वारा पहले एक मान द्वारा वापस किया जाएगा, जिसे ऑपरेटर डिलीट (शून्य *) (17.4.3.7) में हस्तक्षेप करने वाले कॉल द्वारा अमान्य नहीं किया गया था। पीआरटी के इस तरह के एक गैर-शून्य मूल्य के लिए, पहले कॉल द्वारा डिफ़ॉल्ट ऑपरेटर को आवंटित भंडारण पुनः प्राप्त करता है।

संपादित:

जेम्स Kanze here का कहना है कि

यह अभी भी ऑपरेटर के responisiblity हटाएं (या हटाना []) जांच कर सकते हैं; मानक गारंटी नहीं देता है कि इसे एक शून्य सूचक नहीं दिया जाएगा; मानक के लिए आवश्यक है कि अगर कोई शून्य सूचक दिया जाए तो यह नो-ऑप हो। या कार्यान्वयन को इसे कॉल करने की अनुमति है। नवीनतम मसौदे के मुताबिक, "डेलोकेशन फ़ंक्शन को प्रदान किए गए पहले तर्क का मान शून्य सूचक मान हो सकता है; यदि ऐसा है, और यदि मानक लाइब्रेरी में डेलोकेशन फ़ंक्शन एक प्रदान किया जाता है, तो कॉल का कोई प्रभाव नहीं पड़ता है।" मुझे पूरा यकीन नहीं है कि "मानक पुस्तकालय में आपूर्ति की गई" का क्या अर्थ है - सचमुच लिया गया है, क्योंकि उसका कार्य मानक पुस्तकालय द्वारा प्रदान नहीं किया गया है, तो वाक्य लागू नहीं होगा । लेकिन किसी भी तरह, यह समझ में नहीं आता है।

+0

-1 प्रश्न पढ़ें। – wilhelmtell

+2

@ विल्हेल्मटेल: क्या आप एक बड़ा ** नहीं ** देख सकते हैं? –

+0

मैं कर सकता हूं, लेकिन आपकी तर्क स्पष्ट रूप से दिखाती है कि आपने प्रश्न के शीर्षक पर पढ़ना बंद कर दिया है। ओपी * पता * यह डिफ़ॉल्ट मामले में एक नोप है। – wilhelmtell

3

शून्य की जांच करने की कोई आवश्यकता नहीं है। डिलीवरी ऑपरेटर को शून्य के लिए chck करता है तो अतिरिक्त जांच की आवश्यकता नहीं है।

3

delete (T*)0; मान्य है और कुछ भी नहीं करता है, इसी तरह free(NULL); भी मान्य है और कुछ भी नहीं करता है। यदि आप delete ऑपरेटर को अधिभारित करते हैं, तो आपके कार्यान्वयन में समान अर्थशास्त्र होना चाहिए। मानक कहता है कि कैसे मानक delete काम करेगा, लेकिन मुझे नहीं लगता कि यह कहता है कि कैसे एक अधिभारित delete व्यवहार करना चाहिए। मानक/डिफ़ॉल्ट व्यवहार के साथ स्थिरता के लिए, इसे इनपुट के रूप में (T*)0 की अनुमति देनी चाहिए।

3
स्टैंडर्ड डॉक्स से

, 18.5.1.1.13delete के तहत,

डिफ़ॉल्ट व्यवहार: तो ptr रिक्त है, कुछ नहीं करता है। अन्यथा, पहले कॉल द्वारा आवंटित संग्रहण को ऑपरेटर नया पर पुनः दावा किया गया।

तो, आप डिफ़ॉल्ट द्वारा जाँच करने के लिए ..

2

हटाने से पहले शून्य के लिए जाँच करने के लिए कोई ज़रूरत नहीं की जरूरत नहीं है। अगर किसी ने delete को अधिभारित किया है जो किसी मानक तरीके से व्यवहार नहीं करता है तो है जो वास्तविक समस्या है।किसी को भी delete को अधिभारित करने का काम हल्का नहीं करना चाहिए और हमेशा अपेक्षित व्यवहार का समर्थन करना चाहिए जैसे कि न्यूल की जांच करना और कोई कार्रवाई नहीं करना।

void MyObj::reset() 
{ 
    delete impl_; 
    impl_ = 0; // Needed here - impl_ may be reused/referenced. 
} 

MyObj::~MyObj() 
{ 
    delete impl_; // No need to assign here as impl_ is going out of scope. 
} 
6

:

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

और इसलिए, ओवरलोडेड डिलीट को कॉल करते समय, आपको NULL की जांच करनी चाहिए। आपको सही ढंग से कार्यान्वित करने के लिए ओवरलोडेड डिलीट पर भरोसा करना चाहिए।

0

सी ++ पैडेंट्री का थोड़ा सा: NULL अंतर्निहित अवधारणा नहीं है। हां हम सभी जानते हैं कि इसका क्या अर्थ है, लेकिन सी ++ 0 एक्स से पहले सी ++ में नल पॉइंटर अवधारणा केवल मूल्य 0 है। NULL आमतौर पर एक प्लेटफॉर्म-विशिष्ट मैक्रो होता है जो 0.

सी ++ 0 एक्स के साथ हम हैं नलप्टर प्राप्त करना जो एक सादे शून्य से स्पष्ट है और बूल को छोड़कर किसी भी अभिन्न प्रकार में परिवर्तनीय नहीं है, और न्यूल (या शायद एनयूएलएल के पीछे अवधारणा का बेहतर कार्यान्वयन) की तुलना में बेहतर अवधारणा है।

+2

वैकल्पिक रूप से, सी ++ पैडेंट्री के बहुत सारे: एक शून्य सूचक "मान शून्य सूचक" है, नहीं (आवश्यक) मान 0, जो एक पूर्णांक है, सूचक नहीं है। जब एक सूचक प्रकार में परिवर्तित किया जाता है, तो एक स्थिर सूचकांक के साथ एक * स्थिर * पूर्णांक अभिव्यक्ति एक शून्य सूचक में परिणाम (और इसलिए इसे "शून्य सूचक स्थिर" कहा जाता है), लेकिन यह मानक में परिभाषित एक विशेष मामला है। –

+0

ठीक है क्योंकि सी ++ 0 एक्स से पहले भाषा के माध्यम से एक नल पॉइंटर को परिभाषित करने का एकमात्र तरीका निरंतर मूल्य शाब्दिक 0 का उपयोग करना है और जिसके परिणामस्वरूप पॉइंटर अधिभार के बजाय पूर्णांक अधिभार को कॉल करना है, जो वास्तव में pedantic है, - –

+0

शून्य सूचक पाने के अन्य तरीके हैं। उदाहरण के लिए, 'std :: strstr (" a "," b ");'। जाहिर है, एक शून्य सूचक स्थिरांक का उपयोग * समझदार * रास्ता है। मेरा बोनस पेडेंट्री सिर्फ यह इंगित करने के लिए है कि '0' (एक पूर्णांक, और एक शून्य सूचक स्थिरांक, और न्यूल के लिए एक संभावित मूल्य) '(char *) 0' या' (शून्य *) 0' के बीच एक अंतर है (दोनों शून्य पॉइंटर्स, और दोनों शून्य सूचक स्थिरांक, लेकिन न तो C++ में NULL के लिए कानूनी है)। –

2

क्या यह जांच करने के लिए necesary है। अगर कोई भी विधि को अधिभारित करता है, तो उसकी पूरी ज़िम्मेदारी न्यूल के साथ है।

1

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

+0

क्षमा करें, मेरे प्लेटफ़ॉर्म में ऐसी कोई सीमा नहीं है, लेकिन मानते हैं कि एक हमेशा एक पोर्टेबल कोड डिलीट कार्यान्वयन लिखने के लिए अधिकांश बार ओवरलोड किया जाना चाहिए (मेमोरी लीक डिटेक्शन आधारित लॉगिंग, विशेष मेमोरी कार्यान्वयन इत्यादि) तो प्रश्न अभी भी अच्छा है है ना? –

+0

@ एएलएस कंपाइलर/प्लेटफ़ॉर्म कॉन्फ़िगरेशन अंतर्निर्मित प्रकारों (यानी int, char, आदि) के लिए अनिश्चित व्यवहार में जाएगा क्योंकि यह वास्तव में प्लेटफार्मों के मुक्त() कार्यान्वयन के साथ एक बग है, लेकिन इसके लिए कोई फिक्सेस नहीं है यह एक मृत मंच है। – diverscuba23

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

  • कोई संबंधित समस्या नहीं^_^