दिलचस्प पोस्ट
स्विफ्ट के लिए UITableView उदाहरण अर्ध-बृहदान्त्र का पता लगाने के लिए नियमित अभिव्यक्ति सी ++ तथा लूप के दौरान समाप्त होती है पायथन के माध्यम से लिनक्स पर प्रक्रिया सूची एंड्रॉइड स्क्रीन शॉट प्रोग्रामेटिकल रूप से $ दायरे के साथ कार्य करना। $ Emit और $ scope। $ पर JSF 2.0 फ़ाइल अपलोड रिकार्ड ध्वनि क्लिप के साथ एंड्रॉइड पर आवाज मान्यता? एंड्रॉइड में SQLite कैसे एक विशिष्ट पंक्ति को अपडेट करें Grep के माध्यम से कई लाइनों में पैटर्न कैसे ढूंढें? प्रत्येक विधानसभा अनुदेश के लिए कितने CPU चक्र आवश्यक हैं? एक idempotent ऑपरेशन क्या है? python setup.py स्थापना रद्द करें PHP कर्ल और कुकीज़ किस परिस्थिति में एक स्क्वॉश कनेक्शन स्वचालित रूप से एक परिवेश लेन-देन लेन-देन लेन-देन में भर्ती है? एक NSString में एक सबस्ट्रिंग की संख्या की संख्या?

कैसे हटाना पता है कि यह एक सरणी है?

ठीक है, मुझे लगता है कि हम सभी सहमत हैं कि निम्नलिखित कोड के साथ क्या होता है, यह परिभाषित नहीं किया गया है कि क्या पारित किया गया है,

void deleteForMe(int* pointer) { delete[] pointer; } 

संकेतक विभिन्न प्रकार के सभी प्रकार के हो सकते हैं, और इसलिए बिना शर्त delete[] निष्पादित delete[] प्रदर्शन करना अपरिभाषित है। हालांकि, मान लें कि हम वास्तव में एक सरणी सूचक दे ​​रहे हैं,

 int main() { int* arr = new int[5]; deleteForMe(arr); return 0; } 

मेरा सवाल है, इस मामले में, जहां सूचक एक सरणी है, यह कौन जानता है? मेरा मतलब है, भाषा / कंपाइलर के दृष्टिकोण से, यह पता नहीं है कि arr एक सरणी पॉइंटर है, जो कि एक ही int पर पॉइंटर बनाम है अरे, यह भी पता नहीं है कि arr गतिशील रूप से बनाया गया था। फिर भी, अगर मैं इसके बजाय निम्नलिखित करता हूँ,

 int main() { int* num = new int(1); deleteForMe(num); return 0; } 

ओएस बहुत चालाक है कि केवल एक इंट को हटा दें और उसमें से बाकी की स्मृति को हटाकर किसी भी प्रकार की 'हत्या की होड़' पर न जाएं (इसके विपरीत कि स्ट्रेलन और गैर- \0 टर्मिनेटेड स्ट्रिंग के साथ- यह रखेगा जा रहा है जब तक यह हिट 0)।

तो इन कामों को याद करने की किसकी नौकरी है? क्या ओएस पृष्ठभूमि में कुछ प्रकार के रिकॉर्ड रखता है? (मेरा मतलब है, मुझे पता है कि मैंने इस पोस्ट को यह कहते हुए शुरू किया है कि क्या होता है अपरिभाषित है, लेकिन वास्तव में, 'हत्या की स्थिति' नहीं होती है, इसलिए व्यावहारिक दुनिया में कोई याद कर रहा है।)

वेब के समाधान से एकत्रित समाधान "कैसे हटाना पता है कि यह एक सरणी है?"

कंपाइलर को पता नहीं है कि यह एक सरणी है, यह प्रोग्रामर पर भरोसा कर रहा है। हटाए जाने वाले एक एकल int साथ एक पॉइंटर को delete [] अपरिभाषित व्यवहार होता है आपका दूसरा main() उदाहरण असुरक्षित है, भले ही वह तुरंत दुर्घटना न करे।

कंपाइलर को इस बात का ध्यान रखना होगा कि कितने ऑब्जेक्ट्स को किसी भी तरह से हटा दिया जाना चाहिए। यह सरणी आकार को स्टोर करने के लिए पर्याप्त रूप से अधिक आवंटित करके ऐसा कर सकता है। अधिक विवरण के लिए, C ++ Super FAQ देखें

एक प्रश्न जो अब तक दिए गए उत्तरों को संबोधित नहीं करते हैं: यदि रनटाइम लाइब्रेरीज़ (वास्तव में ओएस नहीं हैं) सरणी में चीजों की संख्या का ट्रैक रख सकते हैं, तो हमें सभी को delete[] वाक्यविन्यास की आवश्यकता क्यों है ? सभी हटाए गए कार्यों को संभाल करने के लिए एक भी delete फॉर्म का उपयोग क्यों नहीं किया जा सकता?

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

यही है, अगर आपका कोड बस करता है

 Foo* foo = new Foo; 

फिर foo लिए आवंटित मेमोरी स्पेस में कोई अतिरिक्त ओवरहेड शामिल नहीं होना चाहिए जो Foo सरणियों का समर्थन करने के लिए आवश्यक होगा।

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

 delete[] bar; 

बस के बजाय

 delete bar; 

अगर बार एक सरणी के लिए एक सूचक है

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

हाँ, ओएस 'पृष्ठभूमि' में कुछ चीजें रखती है। उदाहरण के लिए, यदि आप चलाते हैं

 int* num = new int[5]; 

ओएस 4 अतिरिक्त बाइट आवंटित कर सकता है, आवंटित स्मृति के पहले 4 बाइट्स में आबंटन के आकार को स्टोर कर सकता है और ऑफसेट पॉइंटर वापस लौटाता है (यानी यह स्मृति रिक्त स्थान 1000 से 1024 तक आबंटित करता है, लेकिन संकेतक 1004 स्थानों को स्थानांतरित करता है, स्थान 1000- 1003 आवंटन का आकार भंडारण) फिर, जब हटाई जाती है, तो आवंटन के आकार को खोजने के लिए पॉइंटर के पास जाने से पहले यह 4 बाइट्स को देख सकता है।

मुझे यकीन है कि आवंटन के आकार पर नज़र रखने के अन्य तरीके हैं, लेकिन यह एक विकल्प है।

यह इस प्रश्न के समान है और इसके बारे में आपके विवरण में से कई विवरण हैं।

लेकिन यह कहना पर्याप्त है, यह ओएस की नौकरी का काम नहीं करता है। यह वास्तव में रनटाइम लाइब्रेरी या अंतर्निहित स्मृति प्रबंधक है जो सरणी के आकार को ट्रैक करेगा। यह आम तौर पर अतिरिक्त मेमोरी आवंटित करने और उस स्थान में सरणी के आकार को संचयित करने के द्वारा किया जाता है (अधिकतर सिर नोड का उपयोग करते हैं)

यह निम्न कोड निष्पादित करके कुछ कार्यान्वयनों पर देखा जा सकता है

 int* pArray = new int[5]; int size = *(pArray-1); 

delete या delete[] संभवत: दोनों को आवंटित स्मृति (स्मृति इंगित) को मुक्त किया जाएगा, परन्तु बड़ा अंतर यह है कि सरणी को delete सरणी के प्रत्येक तत्व के नाशक को नहीं बुलाएगा।

फिर भी, new/new[] मिश्रण करना और delete/delete[] संभवतः यूबी है

यह पता नहीं है कि यह एक सरणी है, यही वजह है कि आपको नियमित पुराने delete बजाय delete[] delete

मुझे इस पर एक समान सवाल था। सी में, आप malloc () (या किसी अन्य समान फ़ंक्शन) के साथ मेमोरी आवंटित करते हैं, और इसे निशुल्क () से हटाएं केवल एक मॉलोक () है, जो केवल एक निश्चित संख्या में बाइट को आवंटित करता है। केवल एक ही मुफ़्त () है, जो केवल एक सूचक के रूप में लेता है क्योंकि यह पैरामीटर है

तो यह क्यों है कि सी में आप केवल सूचक को मुफ़्त में सौंप सकते हैं, लेकिन सी ++ में आपको यह बता देना चाहिए कि यह एक सरणी या एकल चर है?

जवाब, मैंने सीखा है, कक्षा नाशकों के साथ क्या करना है

यदि आप एक वर्ग MyClass का एक आवंटन आवंटित करते हैं …

 classes = new MyClass[3]; 

इसे हटाने के साथ हटाएं, आप केवल MyClass नाम के पहले उदाहरण के लिए डिस्ट्रक्टर प्राप्त कर सकते हैं। यदि आप [] हटाते हैं, तो आप यह आश्वासन दिया जा सकता है कि सभी उदाहरणों के लिए डिस्ट्रक्टर को सरणी में बुलाया जाएगा।

यह महत्वपूर्ण अंतर है यदि आप बस मानक प्रकार (उदाहरण के लिए int) के साथ काम कर रहे हैं तो आप वास्तव में इस मुद्दे को नहीं देखेंगे इसके अलावा, आपको यह याद रखना चाहिए कि नए [] पर डिलीट करने के लिए व्यवहार और नए पर [] को नष्ट करना अनिर्धारित है – यह हर संकलक / सिस्टम पर समान तरीके से काम नहीं करेगा।

यह रनटाइम पर निर्भर है जो स्मृति आवंटन के लिए ज़िम्मेदार है, उसी तरह कि आप मानक सी में malloc के साथ बनाई गई सरणी का उपयोग मुफ्त में कर सकते हैं। मुझे लगता है कि प्रत्येक कंपाइलर इसे अलग ढंग से लागू करता है एक आम तरीका सरणी आकार के लिए एक अतिरिक्त सेल आवंटित करना है।

हालांकि, रनटाइम यह पता लगाने के लिए काफी चतुर नहीं है कि यह एक सरणी या एक सूचक है, आपको इसे सूचित करना होगा, और यदि आप गलत हैं, तो आप या तो सही तरीके से हटा नहीं सकते (उदाहरण के लिए, सरणी के बजाय ptr), या आप आकार के लिए एक असंबंधित मान लेते हैं और महत्वपूर्ण क्षति का कारण बनते हैं।

कंपाइलर्स के एक दृष्टिकोण में एक छोटे से अधिक मेमोरी आवंटित करना और सिर तत्वों में तत्वों की स्टोर संख्या है।

उदाहरण कैसे किया जा सकता है: यहां

 int* i = new int[4]; 

संकलक sizeof (int) * 5 बाइट आवंटित करेगा।

 int *temp = malloc(sizeof(int)*5) 

पहले sizeof(int) बाइट्स में 4 स्टोर करेगा

 *temp = 4; 

और i सेट

 i = temp + 1; 

तो i 4 तत्वों की सरणी को इंगित करता i , न 5

तथा

 delete[] i; 

निम्नलिखित तरीके से संसाधित किया जाएगा

 int *temp = i - 1; int numbers_of_element = *temp; // = 4 ... call destructor for numbers_of_element elements if needed ... that are stored in temp + 1, temp + 2, ... temp + 4 free (temp) 

सहमत हूँ कि कंपाइलर नहीं जानता है कि यह एक सरणी है या नहीं। यह प्रोग्रामर पर निर्भर है

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

अतिरिक्त संग्रहण के लिए जब अतिरिक्त भंडारण आवंटित किया जाता है, तो कृपया C ++ ABI का संदर्भ लें (कैसे कम्पाइलर लागू होते हैं): Itanium C ++ ABI: ऐरे ऑपरेटर नई कुकीज

सिमेंटिक रूप से, C ++ में हटाए जाने वाले ऑपरेटर के दोनों संस्करण किसी भी सूचक को "खा सकते हैं"; हालांकि, अगर एक ऑब्जेक्ट के एक पॉइंटर को delete[] को delete[] लिए दिया जाता है, तो यूबी का परिणाम होगा, जिसका अर्थ है कि कुछ भी हो सकता है, सिस्टम क्रैश या कुछ भी नहीं।

सी ++ को प्रोग्रामर को डिलोकेशन के विषय के आधार पर डिलीट ऑपरेटर का उचित संस्करण चुनने की आवश्यकता होती है: सरणी या एकल ऑब्जेक्ट

अगर कंपाइलर स्वचालित रूप से यह निर्धारित कर सकता है कि हटाए गए ऑपरेटर को एक पॉइंटर पारित किया गया है या नहीं, तो सूचक सरणी है, तो C ++ में केवल एक ही डिलीट ऑपरेटर होगा, जो दोनों मामलों के लिए पर्याप्त होगा।

आप किसी सरणी के लिए हटाए जाने का उपयोग नहीं कर सकते, और आप गैर-सरणी के लिए [] को नष्ट नहीं कर सकते।

हे हो अच्छी तरह से यह आपके द्वारा नए [] अभिव्यक्ति के साथ आवंटित करने पर निर्भर करता है जब आप प्रकार या कक्षा / संरचना में निर्माण की सरणी आवंटित करते हैं और आप अपने कन्स्ट्रक्टर और डिस्ट्रिक्टर को प्रदान नहीं करते हैं तो ऑपरेटर इसे "आकार (आकृति) आकार के रूप में व्यवहार करेगा ' ऑब्जेक्ट ऐवर्स की बजाय "ऑब्जेक्ट ऑब्जेक्ट्स" की बजाय इस ऑब्जेक्ट ऑब्जेक्ट की संख्या कहीं भी जमा नहीं की जाएगी, हालांकि यदि आप ऑब्जेक्ट ऑरेंज को आवंटित करते हैं और आप वर्डेंट में परिवर्तन से अपने ऑब्जेक्ट में कन्स्ट्रक्टर और डिस्ट्रक्टर प्रदान करते हैं, तो नया एक्सप्रेशन 4 बाइट्स अधिक आवंटित करेगा और संख्या को स्टोर करेगा पहले 4 बाइट्स में ऑब्जेक्ट तो उनमें से हर एक के लिए डिस्ट्रक्टर को बुलाया जा सकता है और इसलिए नया [] अभिव्यक्ति, 4 बाइट्स द्वारा आगे बढ़े सूचक को वापस लौटाएगी, जब मेमोरी वापस की जाती है, तब हटाएं [] अभिव्यक्ति फ़ंक्शन टेम्प्लेट को पहले कॉल करेगी, पुनरावृत्त उनमें से हर एक के लिए वस्तुओं की सरणी और कॉल डिस्ट्रिक्ट के माध्यम से। मैंने इस सरल कोड चुड़ैल ओवरलोड को नया बनाया है [] और [] अभिव्यक्ति को हटाना और आवश्यक होने पर प्रत्येक ऑब्जेक्ट के लिए मेमोरी और कॉल नाशक को हटाना एक टेम्पलेट फ़ंक्शन प्रदान करता है:

 // overloaded new expression void* operator new[]( size_t size ) { // allocate 4 bytes more see comment below int* ptr = (int*)malloc( size + 4 ); // set value stored at address to 0 // and shift pointer by 4 bytes to avoid situation that // might arise where two memory blocks // are adjacent and non-zero *ptr = 0; ++ptr; return ptr; } ////////////////////////////////////////// // overloaded delete expression void static operator delete[]( void* ptr ) { // decrement value of pointer to get the // "Real Pointer Value" int* realPtr = (int*)ptr; --realPtr; free( realPtr ); } ////////////////////////////////////////// // Template used to call destructor if needed // and call appropriate delete template<class T> void Deallocate( T* ptr ) { int* instanceCount = (int*)ptr; --instanceCount; if(*instanceCount > 0) // if larger than 0 array is being deleted { // call destructor for each object for(int i = 0; i < *instanceCount; i++) { ptr[i].~T(); } // call delete passing instance count witch points // to begin of array memory ::operator delete[]( instanceCount ); } else { // single instance deleted call destructor // and delete passing ptr ptr->~T(); ::operator delete[]( ptr ); } } // Replace calls to new and delete #define MyNew ::new #define MyDelete(ptr) Deallocate(ptr) // structure with constructor/ destructor struct StructureOne { StructureOne(): someInt(0) {} ~StructureOne() { someInt = 0; } int someInt; }; ////////////////////////////// // structure without constructor/ destructor struct StructureTwo { int someInt; }; ////////////////////////////// void main(void) { const unsigned int numElements = 30; StructureOne* structOne = nullptr; StructureTwo* structTwo = nullptr; int* basicType = nullptr; size_t ArraySize = 0; /**********************************************************************/ // basic type array // place break point here and in new expression // check size and compare it with size passed // in to new expression size will be the same ArraySize = sizeof( int ) * numElements; // this will be treated as size rather than object array as there is no // constructor and destructor. value assigned to basicType pointer // will be the same as value of "++ptr" in new expression basicType = MyNew int[numElements]; // Place break point in template function to see the behavior // destructors will not be called and it will be treated as // single instance of size equal to "sizeof( int ) * numElements" MyDelete( basicType ); /**********************************************************************/ // structure without constructor and destructor array // behavior will be the same as with basic type // place break point here and in new expression // check size and compare it with size passed // in to new expression size will be the same ArraySize = sizeof( StructureTwo ) * numElements; // this will be treated as size rather than object array as there is no // constructor and destructor value assigned to structTwo pointer // will be the same as value of "++ptr" in new expression structTwo = MyNew StructureTwo[numElements]; // Place break point in template function to see the behavior // destructors will not be called and it will be treated as // single instance of size equal to "sizeof( StructureTwo ) * numElements" MyDelete( structTwo ); /**********************************************************************/ // structure with constructor and destructor array // place break point check size and compare it with size passed in // new expression size in expression will be larger by 4 bytes ArraySize = sizeof( StructureOne ) * numElements; // value assigned to "structOne pointer" will be different // of "++ptr" in new expression "shifted by another 4 bytes" structOne = MyNew StructureOne[numElements]; // Place break point in template function to see the behavior // destructors will be called for each array object MyDelete( structOne ); } /////////////////////////////////////////// 

बस एक वर्ग के अंदर एक विध्वंसक को परिभाषित करें और दोनों वाक्यविन्यास के साथ अपना कोड निष्पादित करें

 delete pointer delete [] pointer 

उत्पादन के अनुसार आप समाधान पा सकते हैं I

उत्तर:

int * pArray = new int [5];

पूर्णांक आकार = * (पीएआरआरए -1);

ऊपर दिखाया गया सही नहीं है और अमान्य मूल्य पैदा करता है। "-1" गणना तत्वों को 64 बिट विंडोज ओएस पर सही बफर आकार पीटीआर -4 बाइट्स एड्रेस में रहता है