स्कॉट मेयर्स अपने प्रभावी सी ++ पुस्तक में कहता है: आइटम 5: नए फॉर्म को हटाने और हटाने के समान फॉर्म का उपयोग करें।
हटाने के लिए बड़ा सवाल यह है: स्मृति में कितनी वस्तुएं रहती हैं? इसका उत्तर यह निर्धारित करता है कि कितने विनाशकों को बुलाया जाना चाहिए।
क्या पॉइंटर हटाया जा रहा है एक ऑब्जेक्ट या ऑब्जेक्ट्स की सरणी पर इंगित करता है? जानने के लिए एकमात्र तरीका यह है कि आप इसे बताने के लिए हैं। यदि आप अपने उपयोग के उपयोग में ब्रैकेट का उपयोग नहीं करते हैं, तो हटाएं कि एक ऑब्जेक्ट की ओर इशारा किया गया है।
इसके अलावा, स्मृति allocator और अधिक स्थान है कि अपने वस्तुओं की दुकान है और इस मामले स्मृति प्रत्येक वस्तु के काम नहीं करेगा के आकार से लौटे ब्लॉक के आकार को विभाजित में करने के लिए आवश्यक आवंटन हो सकता है।
मंच पर निर्भर करता है
, _msize
(विंडोज़), malloc_usable_size
(लिनक्स) या malloc_size
(OSX) कार्यों आप ब्लॉक कि आवंटित किया गया था की वास्तविक लंबाई बता देंगे। बढ़ते कंटेनरों को डिजाइन करते समय इस जानकारी का शोषण किया जा सकता है।
एक और कारण यह काम नहीं करेगा कि Foo* foo = new Foo[10]
मेमोरी आवंटित करने के लिए operator new[]
पर कॉल करता है। फिर स्मृति को हटाने के लिए delete [] foo;
operator delete[]
पर कॉल करें। चूंकि उन ऑपरेटरों को अधिभारित किया जा सकता है, आपको सम्मेलन का पालन करना होगा अन्यथा delete foo;
कॉल operator delete
जो operator delete []
के साथ एक असंगत कार्यान्वयन हो सकता है। यह अर्थशास्त्र की बात है, न कि आवंटित ऑब्जेक्ट की संख्या को ट्रैक करने के बाद, बाद में विनाशक कॉल की सही संख्या जारी करने के लिए।
यह भी देखें:
[16.14] After p = new Fred[n], how does the compiler know there are n objects to be destructed during delete[] p?
लघु जवाब: जादू।
लंबा उत्तर: रन-टाइम सिस्टम ऑब्जेक्ट्स की संख्या संग्रहीत करता है, एन, कहीं कहीं इसे पुनर्प्राप्त किया जा सकता है यदि आप केवल पॉइंटर को जानते हैं, पी। ऐसा दो लोकप्रिय तकनीकें हैं जो ऐसा करती हैं। इन दोनों तकनीकों का वाणिज्यिक-ग्रेड कंपाइलर्स द्वारा उपयोग किया जाता है, दोनों में ट्रेडऑफ हैं, और न ही सही है।ये तकनीकें हैं:
संपादित करें: पढ़ा @AndreyT टिप्पणी करने के बाद, मैं Stroustrup की "डिजाइन और विकास सी के ++" की मेरी कॉपी में खोदा और निम्नलिखित कुछ अंश:
हम कैसे सुनिश्चित करते हैं कि एक सरणी सही ढंग से हटा दिया गया है? विशेष रूप से, हम कैसे सुनिश्चित करते हैं कि विनाशक को सरणी के सभी तत्वों के लिए बुलाया जाता है?
...
सादा हटाना दोनों व्यक्ति को संभालने के लिए आवश्यक नहीं है एक सरणियों वस्तुओं। यह व्यक्तिगत वस्तुओं को आवंटित करने और हटाने के सामान्य मामले को जटिल बनाने से बचाता है। यह सरणी deallocation के लिए आवश्यक जानकारी के साथ व्यक्तिगत वस्तुओं को इकट्ठा करने से बचाता है।
हटाए जाने के एक मध्यवर्ती संस्करण [] को प्रोग्रामर को सरणी के तत्वों की संख्या निर्दिष्ट करने की आवश्यकता होती है।
...
वह बहुत त्रुटियों की संभावना को साबित कर दिया है, इसलिए तत्वों की संख्या का ट्रैक रखने के बोझ के बजाय कार्यान्वयन पर रखा गया था।
जैसा कि @ मार्कस ने उल्लेख किया है, तर्कसंगत हो सकता है कि "आप जो भी उपयोग नहीं करते हैं उसके लिए आप भुगतान नहीं करते हैं"।
EDIT2:
में "सी ++ प्रोग्रामिंग भाषा, 3 संस्करण", §10.4.7, Bjarne Stroustrup लिखते हैं:
वास्तव में कैसे सरणियों और अलग-अलग वस्तुओं आवंटित किए जाते हैं कार्यान्वयन है निर्भर। इसलिए, विभिन्न कार्यान्वयन हटाए गए गलत उपयोगों और [] ऑपरेटरों को हटाने के लिए अलग-अलग प्रतिक्रिया देंगे। पिछले एक जैसे सरल और अनिच्छुक मामलों में, एक कंपाइलर समस्या का पता लगा सकता है, लेकिन आम तौर पर रन टाइम पर कुछ बुरा होगा।
सरणी के लिए विशेष विनाश ऑपरेटर, हटाएं [], तर्कसंगत रूप से आवश्यक नहीं है। हालांकि, मान लें कि मुक्त स्टोर के कार्यान्वयन के लिए प्रत्येक ऑब्जेक्ट के लिए पर्याप्त जानकारी रखने की आवश्यकता थी ताकि यह बताने के लिए कि यह एक व्यक्ति या सरणी है या नहीं। उपयोगकर्ता को बोझ से मुक्त किया जा सकता था, लेकिन उस दायित्व ने कुछ सी ++ कार्यान्वयन पर महत्वपूर्ण समय और अंतरिक्ष ओवरहेड लगाया होगा।
स्कॉट मेयर्स पुस्तक के लिए +1: _all_ C++ प्रोग्रामर को प्रभावी सी ++ और अधिक प्रभावी सी ++ पुस्तकों का स्वामित्व और पढ़ना चाहिए। – AAT
स्कॉट की * स्पष्टीकरण * वास्तव में बिल्कुल एक स्पष्टीकरण नहीं है। यह तथ्य का केवल एक अनुमान है, चालाकी से "स्पष्टीकरण" के रूप में पारित किया गया। वह कहता है कि यह जानने का एकमात्र तरीका है कि यह एक सरणी या एक वस्तु है, उपयोगकर्ता से पूछना है। यह निश्चित रूप से गलत है। उस जानकारी को 'नए []' में संग्रहीत करना पूरी तरह से संभव है और फिर 'डिलीट' में पुनर्प्राप्त करें, जैसा कि अब तत्व गणना के साथ किया गया है। निर्णय इसके खिलाफ किया गया था, क्योंकि यह अत्यधिक "जटिल" सूचना संरचना और 'हटाए' में शाखाबद्ध होगा। कोई "प्यारा" स्पष्टीकरण नहीं है, यह बस * तय * था। – AnT
@ जेसन: नहीं, स्कॉट की व्याख्या पूरी तरह से फर्जी है। फिर, आप कैसे जानते हैं कि जब आप 'हटाएं'] करते हैं तो सरणी में कितने तत्व हैं? है ना? क्या आपको इसे 'हटाएं []' करने के लिए कहना है? नहीं। हटाएं [] '" जानता है "क्योंकि यह 'नई []' द्वारा तैयार की गई घरेलू जानकारी का उपयोग करता है। वैसे ही हम "सरणी या नहीं" प्रकृति की अतिरिक्त घरेलू जानकारी को स्टोर करने के लिए 'new' \' new [] 'को मजबूर कर सकते हैं। यह आसान और स्पष्ट है। यह आपके प्रश्न का उत्तर है। – AnT