2009-04-01 5 views
108

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

  1. प्रदर्शन:

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

  2. यह const पॉइंटर्स के कारण हो सकता है।

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

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

उत्तर

138

Stroustrup himself उत्तर। एक अंश:

सी ++ स्पष्ट एक lvalue संकार्य को शून्य करने के लिए हटाने की एक कार्यान्वयन की अनुमति देता है, और मैं उम्मीद थी कि कार्यान्वयन करना होगा कि, लेकिन उस विचार साथ लोकप्रिय हो गए हैं प्रतीत नहीं होता है इसको लागू करने।

लेकिन मुख्य मुद्दा वह उठाता है कि हटाए जाने वाले तर्क को एक लालसा नहीं होना चाहिए।

12

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

+1

या सूचक के संदर्भ में। –

+0

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

5

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

54

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

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

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

+4

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

+0

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

+0

@PravasiMeet नहीं, मेरा मतलब है 'हटाएं (पीआरटी + i) ' – sharptooth

35

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

17

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

है कि इसके अलावा, आप अपने खुद के समारोह करता है कि आप क्या चाहते हैं बना सकते हैं:

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

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

3

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

4

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

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

7

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

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

T* const foo = new T; 
delete foo; 
4

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

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

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

-2

मैं लोगों को इस प्रश्न के अजीब जवाब देने वाले लोगों को देखता हूं।

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

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

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

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

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

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