हटाए गए सूचक को NULL पर क्यों नहीं हटाया जाता?


127

मैं हमेशा सोचता था कि डिलीट के बाद NULL को पॉइंटर की स्वचालित सेटिंग मानक का हिस्सा क्यों नहीं है। यदि इस पर ध्यान दिया जाता है तो एक अवैध पॉइंटर के कारण कई क्रैश नहीं होंगे। लेकिन यह कहते हुए कि मैं दो कारणों के बारे में सोच सकता हूं कि मानक ने इसे प्रतिबंधित क्यों किया होगा:

  1. प्रदर्शन:

    एक अतिरिक्त निर्देश deleteप्रदर्शन को धीमा कर सकता है ।

  2. यह constसंकेत की वजह से हो सकता है ।

    तब फिर से मानक इस विशेष मामले के लिए कुछ कर सकता था मुझे लगता है।

क्या किसी को इसकी अनुमति नहीं देने के सटीक कारण पता हैं?

जवाबों:


150

स्ट्रॉस्ट्रुप खुद जवाब देता है। अंश:

C ++ स्पष्ट रूप से एक लैवल्यू ऑपरेंड को शून्य करने के लिए कार्यान्वयन को लागू करने की अनुमति देता है, और मुझे उम्मीद थी कि कार्यान्वयन ऐसा करेंगे, लेकिन ऐसा नहीं लगता है कि कार्यान्वयनकर्ताओं के साथ लोकप्रिय हो गए हैं।

लेकिन वह मुख्य मुद्दा यह उठाता है कि डिलीट के तर्क की आवश्यकता नहीं है।


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

63

सबसे पहले, शून्य पर सेट करने के लिए मेमोरी मेमोरी वेरिएबल की आवश्यकता होगी। यह सच है, कि आपके पास आमतौर पर एक चर में एक संकेतक होता है, लेकिन कभी-कभी आप किसी गणना वाले पते पर किसी ऑब्जेक्ट को हटाना चाह सकते हैं । यह "अशक्त" हटाने के साथ असंभव होगा।

इसके बाद प्रदर्शन आता है। आपने कोड को इस तरह लिखा होगा कि डिलीट होने के तुरंत बाद पॉइंटर दायरे से बाहर हो जाएगा । इसे शून्य से भरना सिर्फ समय की बर्बादी है। और सी ++ एक ऐसी भाषा है, "जिसकी आवश्यकता नहीं है? फिर आपको इसके लिए भुगतान करने की आवश्यकता नहीं है" विचारधारा।

यदि आपको सुरक्षा की आवश्यकता है तो आपके पास सेवा में स्मार्ट पॉइंटर्स की एक विस्तृत श्रृंखला है या आप अपने खुद के - बेहतर और स्मार्ट लिख सकते हैं।


4
अच्छा बिंदु wrt गणना पता, भले ही यह ऐसा कुछ हो जो आप अक्सर नहीं देखते हैं
snemarch

क्या आप प्लेसमेंट नए के बारे में बात कर रहे हैं, जब आप कहते हैं कि कभी-कभी आप किसी गणना किए गए पते पर किसी ऑब्जेक्ट को हटाना चाहते हैं। ???
विध्वंसक

@PravasiMeet नहीं, मेरा मतलब कुछ इस तरह हैdelete (ptr + i)
शार्प्यूट

39

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


19

एक पॉइंटर को एक से अधिक वेरिएबल में सेव किया जा सकता है, इनमें से एक को NULL में सेट करने से दूसरे वेरिएबल्स में अमान्य पॉइंटर्स निकल जाएंगे। इसलिए आप वास्तव में बहुत लाभ नहीं उठाते हैं, आप सुरक्षा की झूठी भावना पैदा करने की अधिक संभावना रखते हैं।

इसके अलावा, आप अपना खुद का फ़ंक्शन बना सकते हैं जो आपको चाहिए:

template<typename T>
void deleten(T *&ptr) {
  delete ptr;
  ptr = NULL;
}

12

क्योंकि वास्तव में इसकी कोई आवश्यकता नहीं है, और क्योंकि इसे केवल सूचक के बजाय सूचक-से-सूचक को हटाने की आवश्यकता होगी।


सच है, लेकिन इसके परिणामस्वरूप एक ही ओवरहेड होगा
स्नैमार्क

7

deleteज्यादातर विध्वंसक में उपयोग किया जाता है, जिस स्थिति में सदस्य को NULL में सेट करना व्यर्थ है। समापन के कुछ समय बाद, }सदस्य अब मौजूद नहीं है। असाइनमेंट ऑपरेटरों में, एक डिलीट को आमतौर पर किसी असाइनमेंट द्वारा अनुसरण किया जाता है।

इसके अलावा, यह निम्नलिखित कोड को अवैध करेगा:

T* const foo = new T;
delete foo;

6

यहाँ एक और कारण है; मान लें कि डिलीट ने NULL को अपना तर्क सेट कर दिया है:

int *foo = new int;
int *bar = foo;
delete foo;

क्या बार को NULL पर सेट होना चाहिए? क्या आप इसे सामान्य कर सकते हैं?


5

यदि आपके पास पॉइंटर्स का एक सरणी है, और आपकी दूसरी क्रिया खाली सरणी को हटाने के लिए है, तो स्मृति को मुक्त करने के लिए प्रत्येक मान को शून्य करने के लिए कोई बिंदु सेट नहीं है। अगर आप चाहते हैं कि यह अशक्त हो जाए .. इसे अशक्त लिखें :)


4

C ++ आपको अपने स्वयं के ऑपरेटर को नए रूप में परिभाषित करने और हटाने की अनुमति देता है ताकि उदाहरण के लिए वे आपके अपने पूल आवंटनकर्ता का उपयोग करें। यदि आप ऐसा करते हैं तो नए का उपयोग करना और उन चीजों से हटाना संभव है जो कड़े पते नहीं हैं, लेकिन अपने पूल ऐरे में इंडेक्स कहें। इस संदर्भ में NULL (0) का मान कानूनी अर्थ हो सकता है (पूल में पहले आइटम का जिक्र)।
तो हटाए गए NULL को अपने तर्क में स्वचालित रूप से हटाने का हमेशा मतलब नहीं होता है - मान को अमान्य मान पर सेट करें। अमान्य मान हमेशा NULL नहीं हो सकता है।


4

C ++ का दर्शन "इसके लिए भुगतान तभी करें जब आप इसका उपयोग करें"। मुझे लगता है कि यह आपके सवाल का जवाब दे सकता है।

इसके अलावा कभी-कभी आपके पास अपना खुद का ढेर हो सकता है जो हटाए गए स्मृति को पुनर्प्राप्त करेगा .. या कभी-कभी सूचक किसी भी चर के स्वामित्व में नहीं होगा। या पॉइंटर को कुछ चरों में संग्रहीत किया जाता है - यह संभव है कि उनमें से सिर्फ एक ही शून्य हो।
जैसा कि आप देख सकते हैं कि इसमें कई मुद्दे और संभावित समस्याएं हैं।


3

NULL के लिए पॉइंटर को स्वचालित रूप से सेट करना खराब पॉइंटर उपयोग के अधिकांश मुद्दों को हल नहीं करेगा। यदि आप इसे दो बार हटाने का प्रयास करते हैं तो एकमात्र दुर्घटना इससे बच जाएगी। यदि आप ऐसे पॉइंटर पर एक सदस्य फ़ंक्शन कहते हैं तो क्या होगा? यह अभी भी क्रैश होगा (यह मानते हुए कि यह सदस्य चर को एक्सेस करता है)। C ++ आपको NULL पॉइंटर्स पर किसी भी फ़ंक्शन को कॉल करने से प्रतिबंधित नहीं करता है, और न ही प्रदर्शन के दृष्टिकोण से ऐसा करना चाहिए।


-1

मैं लोगों को इस सवाल का अजीब जवाब देता हूं।

पीटीआर = पूर्ण; इस तरह के एक साधारण बयान से प्रदर्शन में देरी कैसे हो सकती है?

एक अन्य उत्तर यह कह रहा है कि हम एक ही मेमोरी लोकेशन की ओर इशारा करते हुए कई पॉइंटर्स रख सकते हैं। निश्चित रूप से हम कर सकते हैं। इस स्थिति में, एक पॉइंटर पर डिलीट ऑपरेशन केवल वही पॉइंटर NULL (यदि डिलीट पॉइंटर NULL बना रहा था) बना देगा और दूसरा पॉइंटर नॉन-NULL होगा और मेमोरी लोकेशन की ओर इशारा करेगा जो कि मुफ़्त है।

इसके लिए समाधान यह होना चाहिए कि उपयोगकर्ता एक ही स्थान की ओर इशारा करते हुए सभी बिंदुओं को हटा दें। आंतरिक रूप से यह जांचना चाहिए कि क्या मेमोरी पहले से मुक्त नहीं है। केवल पॉइंटर को NULL करें।

Stroustrup इस तरीके से काम करने के लिए डिलीट डिज़ाइन कर सकता था। उसने सोचा कि प्रोग्रामर इस बात का ध्यान रखेंगे। इसलिए उन्होंने नजरअंदाज कर दिया।

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