दिलचस्प पोस्ट
जांचें कि कोई सरणी दूसरे का सबसेट है या नहीं एक WCF सेवा के लिए डेटा इंजेक्शन AsyncTask doInBackground विधि को बंद करें जीसीसी के लिए एक संकलक संकेत क्या शाखा भविष्यवाणी को हमेशा एक निश्चित तरीके से जाने के लिए मजबूर करता है? CSS3 के साथ हेक्सागोनल पैटर्न दोहराते उत्पन्न करें क्या इनटस्टस्ट्रीम से टाइमआउट के साथ पढ़ना संभव है? जावा का उपयोग कर वर्तमान मशीन का आईपी पता प्राप्त करना मैक बंडल में फ़ॉन्ट एम्बेड करें PHP / अपाचे / AJAX – पोस्ट सीमा? सम्मिलित करें यदि मौजूद नहीं है, और फिर postgresql में आईडी वापसी कैसे AJAX (कोई jquery) द्वारा multipart / form-data फ़ॉर्म सामग्री भेजने के लिए? जावा के साथ डीओएम पार्सिंग में सामान्यकरण – यह कैसे काम करता है? काउंटर नाम डेटा लोड नहीं किया जा सकता है क्योंकि एक अमान्य अनुक्रमणिका -अपापन सी ++ क्रॉस प्लेटफॉर्म उच्च-रिज़ॉल्यूशन टाइमर C # WebClient के साथ एक फॉर्म जमा करें

क्या यह एक नाशक में शून्य के लिए पॉइंटर्स सेट करना उचित है?

कल्पना कीजिए कि मेरे पास एक ऐसा वर्ग है जो स्मृति को आवंटित करता है (अब के लिए स्मार्ट पॉइंटर्स के बारे में भूल जाओ):

class Foo { public: Foo() : bar(new Bar) { } ~Foo() { delete bar; } void doSomething() { bar->doSomething(); } private: Bar* bar; }; 

साथ ही साथ डिस्ट्रिक्ट में ऑब्जेक्ट्स को हटाना भी उन्हें नाउल करने के लिए लायक है?

मैं मान रहा हूं कि उपरोक्त उदाहरण के नाशक में पॉइंटर की स्थापना को समय की बर्बादी है।

Solutions Collecting From Web of "क्या यह एक नाशक में शून्य के लिए पॉइंटर्स सेट करना उचित है?"

चूंकि नाशक आखिरी चीज है जिसे किसी वस्तु पर "मर जाता है" से पहले कहा जाता है, इसलिए मैं कहूंगा कि बाद में इसे NULL करने की कोई आवश्यकता नहीं है।

किसी भी अन्य मामले में, मैं हमेशा उस पर delete करने के बाद एक सूचक को NULL पर सेट करता हूं।

कई जवाबों में यह उल्लेख किया गया है कि यह डीबगिंग में सहायता करने के लिए डिबग बिल्डिंग में ऐसा करने के लिए उपयुक्त होगा।

ऐसा मत करो

आप केवल संभावित रूप से एक डिबग बिल्ड में एक समस्या को छिपाने में सहायता करेंगे, जो कि आपकी रिहाई में छिपी नहीं है, जो कि आप वास्तव में ग्राहकों को देते हैं (जो कि आपके डिबग बिल्ड होने चाहिए इसका विपरीत प्रभाव है)।

यदि आप 'डीटीओआर' में सूचक को 'साफ़' करने जा रहे हैं, तो एक अलग मुहावरे बेहतर होगा – पॉइंटर को ज्ञात बुरे पॉइंटर वैल्यू में सेट करें। इस तरह यदि वस्तु का एक झुर्रियों वाला संदर्भ कहीं है जो अंततः संकेतक का उपयोग करने की कोशिश करता है, तो आपको संकेतक के प्रयोग से बचने वाली छोटी गाड़ी कोड के बजाय एक नैदानिक ​​दुर्घटना मिलेगी क्योंकि यह नोटिस है कि यह नल है

कहें कि doSomething() जैसा दिखता है:

 void doSomething() { if (bar) bar->doSomething(); } 

फिर नल को सेट करने से सिर्फ एक बग को छिपाने में मदद मिली है अगर हटाए गए Foo ऑब्जेक्ट के लिए झूठी संदर्भ है जो Foo::doSomething() नामक है।

यदि आपका पॉइंटर साफ हो जाता है:

 ~Foo() { delete bar; if (DEBUG) bar = (bar_type*)(long_ptr)(0xDEADBEEF); } 

आपके पास बग को पकड़ने का बेहतर मौका हो सकता है (हालांकि अकेले bar अकेले छोड़ने के लिए शायद इसी तरह का प्रभाव होगा)

अब अगर किसी चीज को Foo ऑब्जेक्ट को नष्ट कर दिया गया है, तो किसी bar उपयोग किसी नल की जांच के कारण इसे किसी भी प्रकार से संदर्भित नहीं कर सकता है – यह संकेतक का उपयोग करने की खुशी से प्रयास करेगा और आपको एक दुर्घटना मिलेगी जिसे आप ठीक कर सकते हैं डिबग बिल्ड्स में कुछ भी बुरा नहीं होने के बजाय, लेकिन आपके ग्राहक की रिहाई में अभी भी लंघन संदर्भ (खराब प्रभाव से) का उपयोग किया जा रहा है

जब आप डीबग मोड में संकलन कर रहे हैं, तो संभावना बहुत अच्छी है कि डीबग हेप प्रबंधक पहले से ही आपके लिए यह कर रहा होगा (कम से कम एमएसवीसी के डिबग रनटाइम हेप मैनेजर स्मृति को मृत / मुक्त होने के संकेत के लिए 0xDD के साथ मुक्त स्मृति को अधिलेखित कर देगा) ।

महत्वपूर्ण बात यह है कि यदि आप कक्षा के सदस्यों के रूप में कच्चे पॉइंटर्स का उपयोग कर रहे हैं, तो डॉटोर रन होने पर पॉइंटर्स को नल से सेट न करें।

यह नियम अन्य कच्चे पॉइंटर्स पर भी लागू हो सकता है, लेकिन यह उस पर निर्भर करता है कि सूचक का उपयोग कैसे किया जाता है।

हाँ, यह समय की बर्बादी है

आपको दो कारणों से नहीं जाना चाहिए:

  • यह डीबगिंग की सहायता करता है, लेकिन आधुनिक वातावरण में, हटाए गए ऑब्जेक्ट्स को आमतौर पर डिबग बिल्ड्स में पहचानने योग्य बिट पैटर्न के साथ पहले से लिखा गया है।

  • एक बड़े आवेदन में, यह शटडाउन प्रदर्शन को काफी नीचा दिखा सकता है। सबसे खराब स्थिति में, आपके ऐप का मतलब बंद करने के कई अलग-अलग डिस्ट्रक्टरों को बुलाते हैं, और सैकड़ों हेप पेजों को लिखना जो वर्तमान में डिस्क पर स्वैप किए जाते हैं।

सबसे पहले, यह एक सी अभ्यास है, और एक विवादास्पद एक है। कुछ लोग तर्क देते हैं (सी के लिए) कि यह बग्स को छुपाता है जो जल्द ही उपयोग नहीं किया जाता है, और जो किसी एक के उपयोग से मुक्त स्मृति हिस्से के इस्तेमाल को अलग नहीं करना असंभव है, जिसे कभी भी आवंटित नहीं किया गया था …

अब सी ++ में? यह बेकार है, लेकिन सी के मुकाबले एक ही कारण से नहीं।

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

अंत में, एक नाशक में यह वास्तव में पूरी तरह से बेकार है … एक वस्तु के किसी भी क्षेत्र को पहुंचने के बाद एक नाशक चलाया जाता है अपरिभाषित व्यवहार। आपने स्मृति को जारी किया है, इसलिए वहां पर कुछ और लिखा जा सकता है, जो आपकी सावधानी से रखा नल को ओवरराइट कर सकता है और वास्तव में, जिस तरह से मेमोरी आवर्तक काम करते हैं, वे अक्सर ताज़ा deallocated zones को पुन: निर्दिष्ट करने के लिए होते हैं: यह कैशिंग प्रदर्शन को बढ़ाता है … और यह बिल्कुल सच्ची (हाहा!) है अगर हम ढेर के बारे में बात कर रहे हैं, बिल्कुल।

मेरी राय: SAFE_DELETE आसन्न कयामत का एक संकेत है

वास्तव में डीबगिंग कारणों के लिए इसके लायक हो सकता है

आम तौर पर, नहीं, पॉकेटर्स को NULL में हटाने के बाद उन्हें स्पष्ट रूप से सेट करने की कोई आवश्यकता नहीं है – हालांकि ये क्लाउड के निरीक्षण के दौरान डीबगिंग के दौरान एक उपयोगी सहायता हो सकती है, यह इंगित करने के लिए कि कोई संसाधन सही तरीके से मुक्त है या नहीं।

एक आम मुहावरा एक SAFE_DELETE मैक्रो घोषित करना है, जो सूचक को हटा देता है और इसे आपके लिए NULL सेट करता NULL :

 #define SAFE_DELETE(x) delete (x); x = NULL SAFE_DELETE(bar) 

यह उन मामलों में विशेष रूप से उपयोगी होता है जहां संकेतक बाद में पुन: उपयोग कर सकते हैं।

IMO इसकी कीमत DEBUG मोड में। मुझे बार-बार सहायक लगता है रिलीज़ मोड में यह आमतौर पर कोड ऑप्टिमाइज़ेशन के कारण कंपाइलर द्वारा छोड़ा जाता है, इसलिए आपको वास्तव में इस पर अपने प्रोडक्शन कोड पर भरोसा नहीं करना चाहिए।

मैं सभी कीमतों पर कच्चे पॉइंटर्स से बचना चाहूंगा, उदाहरण के बिना और स्मार्ट पॉइंट के बिना जहां यह नल को स्थापित करना स्पष्ट रूप से उपयोगी है:

साथ में:

  class foo { public: foo() : m_something( new int ) { } void doStuff() { // delete + new again - for whatever reason this might need doing m_something.reset( new int ); } private: std::unique_ptr<int> m_something; // int as an example, no need for it to be on the heap in "real" code } 

के बग़ैर:

 class foo { public: foo() : m_something( new int ) { } ~foo() { delete m_something; } void doStuff() { delete m_something; // Without this, if the next line throws then the dtor will do a double delete m_something = nullptr; m_something = new int; } private: int* m_something } 

नहीं, यह इसके लायक नहीं है

लेकिन अगर आप संगत रहना चाहते हैं तो आपको शायद यह करना चाहिए।

आम तौर पर मैं क्या करूँगा एक नि: शुल्क समारोह बनाने के लिए कि मैं आवंटित डेटा को मुक्त करने के लिए हर बार उपयोग कर सकता हूं (यदि आवश्यक हो तो ईवेंट अधिक नि: शुल्क फ़ंक्शन)। उन कार्यों में आपको संकेत दिया जाता है कि वे पॉइंटर्स को नल (या पहचानकर्ता को एक अमान्य मूल्य पर सेट करें)।

मुझे लगता है कि यह हमेशा ऐसा करना लायक है (भले ही आपको तकनीकी की आवश्यकता नहीं है)। मैंने एक पॉइंटर को नाउल के लिए सेट किया है, यह इंगित करने के लिए मेमोरी को इंगित करता है कि उसे deallocated की आवश्यकता नहीं है।

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

 if (NULL == pSomething) { // Safe to operate on pSomething } else { // Not safe to operate on pSomething } 

यदि पहले से हालत गार्ड में अनजाने में सेट करने से पहले शून्य हो जाता है, तो जब आप पर्ची और दूसरा '=' बाहर निकल जाएं आप एक बग की बजाय एक संकलन त्रुटि प्राप्त करते हैं, जिससे नीचे ट्रैक करने में समय लगता है।

उनको हटाने के बाद पॉइंट्स हमेशा सेट करने के लिए अच्छा अभ्यास है। इसके अलावा कुछ कोड जाँच करने वाले उपकरण इसे लागू करते हैं।