C ++ में डिलीट vs डिलीट [] ऑपरेटर्स


136

बीच क्या अंतर है deleteऔर delete[]सी ++ में ऑपरेटरों?


आप इस सवाल प्रासंगिक मिल सकती है stackoverflow.com/questions/1913343/...
sharptooth

7
डिलीट और डिलीट करने वाले मुद्दे [] एक कारण है कि मुझे स्मार्ट पॉइंटर्स पसंद हैं, और vector<>जब भी मैं कर सकता हूं एक एरे के बजाय उपयोग कर रहा हूं।
डेविड थॉर्नले


@DavidThornley यदि आप स्मार्ट पॉइंटर्स का उपयोग कर रहे हैं, तो आपको अभी भी इस अर्थ में अंतर जानने की आवश्यकता है कि आपको अभी भी लिखने की आवश्यकता नहीं है जैसे कि std::unique_ptr<int>(new int[3]), उदाहरण के लिए , यह deleteउस सरणी पर नियमित रूप से कॉल करेगा जो अपरिभाषित व्यवहार है। इसके बजाय आपको उपयोग करने की आवश्यकता हैstd::unique_ptr<int[]>
आर्थर टक्का

जवाबों:


151

deleteऑपरेटर स्मृति deallocates और के साथ बनाई गई एक वस्तु के लिए नाशक कॉल new

delete []ऑपरेटर के साथ बनाई गई वस्तुओं की एक सरणी के लिए स्मृति और कॉल विनाशकर्ता deallocatesnew []

deleteएक सूचक का उपयोग करके new []या delete []एक सूचक द्वारा newअपरिभाषित व्यवहार में परिणाम द्वारा लौटाया गया ।


3
मुझे आश्चर्य है कि इंटिमेट या चार (कोई कंस्ट्रक्टर / डिस्ट्रक्टर) जैसे आदिम प्रकार के नए [] सरणी पर डिलीट का उपयोग करने से आवश्यक रूप से अपरिभाषित व्यवहार होता है। ऐसा लगता है कि आदिम प्रकारों का उपयोग करते समय सरणी आकार कहीं भी संग्रहीत नहीं है।
थोमियल

21
यदि मानक परिभाषित नहीं करता है कि जब ऐसा किया जाता है, तो यह परिभाषा "अपरिभाषित व्यवहार" से होता है, भले ही आपका कंपाइलर निर्धारित करता है कि आप क्या करना चाहते हैं। एक और संकलक पूरी तरह से अलग कुछ कर सकता है।
रोब के

मुझे यह त्रुटि तब हुई जब मेरे पास "char ** strArray" जैसे C स्ट्रिंग्स की एक सरणी थी। यदि आपके पास मेरी तरह एक सरणी है, तो आपको सरणी के माध्यम से पुनरावृति करने और प्रत्येक तत्व को हटाने / मुक्त करने की आवश्यकता है, फिर स्वयं को हटाएं / मुक्त करें। सरणी पर "हटाएं []" का उपयोग करने के बाद से मैं काम नहीं करता हूं (जैसा कि ऊपर की टिप्पणियों और उत्तर द्वारा इंगित किया गया है), आईटी कॉल डेस्क, यह वास्तव में प्रत्येक स्लॉट को मुक्त नहीं करता है।
कटनी

88

delete[]ऑपरेटर हटाने सरणियों किया जाता है। deleteऑपरेटर गैर सरणी वस्तुओं को हटाने के लिए प्रयोग किया जाता है। यह मेमोरी को हटाने के लिए क्रमशः कॉल करता है operator delete[]और operator deleteकार्य करता है कि सरणी के तत्वों या गैर-सरणी ऑब्जेक्ट के लिए विध्वंसक को कॉल करने के बाद (अंततः) कब्जे वाली सरणी या गैर-सरणी ऑब्जेक्ट।

निम्नलिखित संबंधों को दर्शाता है:

typedef int array_type[1];

// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;

// create and destroy an int
int *b = new int;
delete b;

// create and destroy an int[1]
int *c = new int[1];
delete[] c;

// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;

के लिए new है कि एक सरणी बनाता है (हां, तो या तो new type[]या newएक सरणी प्रकार निर्माण करने के लिए लागू), एक के लिए मानक दिखता operator new[]सरणी के तत्व प्रकार कक्षा में या वैश्विक क्षेत्र में, और अनुरोध किया स्मृति की मात्रा से गुजरता है। N * sizeof(ElementType)यदि यह चाहता है कि यह अधिक से अधिक अनुरोध कर सकता है (उदाहरण के लिए तत्वों की संख्या को संग्रहीत करने के लिए, इसलिए बाद में जब हटाने से पता चलता है कि कितने विध्वंसक कॉल किए जाते हैं)। यदि कक्षा घोषित करती है operator new[]कि स्मृति की मात्रा को अतिरिक्त कोई और स्वीकार करता हैsize_t , तो दूसरा पैरामीटर आवंटित तत्वों की संख्या प्राप्त करेगा - यह किसी भी उद्देश्य के लिए इसका उपयोग कर सकता है (डिबगिंग, आदि ...)।

इसके लिए newएक गैर-सरणी ऑब्जेक्ट बनाता है, यह operator newतत्व के वर्ग में या वैश्विक दायरे में दिखेगा । यह अनुरोधित मेमोरी की मात्रा ( sizeof(T)हमेशा हमेशा) पास करता है।

इसके लिए delete[], यह सरणियों के तत्व वर्ग प्रकार में दिखता है और उनके विनाशकों को बुलाता है। operator delete[]उपयोग किया जाने वाला फ़ंक्शन तत्व प्रकार की कक्षा में एक है, या यदि वैश्विक दायरे में कोई नहीं है।

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


18

C ++ malloc/ free, new/ delete, new[]/ में पैटर्न आवंटित / डीए-आवंटित करने का यह मूल उपयोग है delete[]

हमें उन्हें इसी तरह उपयोग करने की आवश्यकता है। लेकिन मैं के बीच अंतर के लिए इस विशेष समझ जोड़ना चाहते हैं deleteऔरdelete[]

1) deleteका उपयोग सिंगल ऑब्जेक्ट के लिए आवंटित मेमोरी को डी-आवंटित करने के लिए किया जाता है

2) वस्तुओं की सरणी केdelete[] लिए आवंटित मेमोरी को डी-आवंटित करने के लिए उपयोग किया जाता है

class ABC{}

ABC *ptr = new ABC[100]

जब हम कहते हैं new ABC[100] , संकलक को यह जानकारी मिल सकती है कि कितनी वस्तुओं को आवंटित करने की आवश्यकता है (यहाँ यह 100 है) और निर्मित वस्तुओं में से प्रत्येक के लिए निर्माता को कॉल करेगा

लेकिन तदनुसार यदि हम delete ptrइस मामले के लिए उपयोग करते हैं, तो संकलक को पता नहीं चलेगा कि कितनी वस्तुएं हैंptr इंगित कर रहे हैं और केवल 1 ऑब्जेक्ट के लिए विध्वंसक और मेमोरी को हटाने का आह्वान करेंगे और (शेष 99 ऑब्जेक्ट के डिस्ट्रक्टर्स और डिक्लोकेशन के आमंत्रण को छोड़कर)। इसलिए स्मृति रिसाव होगा।

इसलिए हमें delete [] ptrइस मामले में उपयोग करने की आवश्यकता है ।


3
यह सही उत्तर होना चाहिए। अन्य उत्तरों में से कोई भी भिन्न अंतर का उल्लेख नहीं करता है: "लेकिन इसी तरह यदि हम इस मामले के लिए बस ptr को हटाते हैं, तो संकलक को पता नहीं चलेगा कि ptr कितनी वस्तुओं को इंगित कर रहा है और केवल 1 ऑब्जेक्ट के लिए विध्वंसक और मेमोरी हटाने की कॉलिंग को समाप्त करेगा।"
डॉन लैरिंक्स

1
हम सी में एक ही चीज कैसे हासिल करते हैं?
डॉगस यूराल

@DogusUral क्यों? C में कोई विध्वंसक नहीं हैं, इसलिए आप बस free()यही और वह। यदि आप एक छद्म-विध्वंसक पैटर्न का उपयोग करते हैं, तो आपको forलूप का उपयोग करके प्रत्येक ऑब्जेक्ट के लिए एक बार कॉल करना होगा ।
कोटसकस

@DonLarynx सही अंतर यह है कि उन्हें एक बीमार कार्यक्रम में परिणाम मिलाता है । एक कार्यान्वयन से पता चल सकता है कि कितनी वस्तुओं को नष्ट करना है, या यह नहीं हो सकता है । यह जानने की अनुमति है कि इसे गलत कहा गया था, और आपको यह बताकर कार्यक्रम रद्द कर देना चाहिए कि समस्या कहां है।
Caleth

6

संचालक delete और delete []के साथ बनाई गई वस्तुओं को नष्ट करने के क्रमशः उपयोग किया जाता है newऔर new[], आबंटित स्मृति की ओर लौटने संकलक की स्मृति प्रबंधक के लिए उपलब्ध छोड़ दिया है।

newआवश्यक रूप से बनाई गई वस्तुओं को नष्ट कर दिया जाना चाहिए delete, और इसके साथ बनाई गई सरणियों new[]को हटा दिया जाना चाहिए delete[]


2

जब मैंने यह सवाल पूछा, तो मेरा असली सवाल था, "क्या दोनों के बीच कोई अंतर है? क्या रनटाइम को सरणी आकार के बारे में जानकारी नहीं रखनी है, और इसलिए क्या यह बताने में सक्षम नहीं होगा कि हम किसका मतलब है?" यह प्रश्न "संबंधित प्रश्नों" में प्रकट नहीं होता है, इसलिए सिर्फ मेरे जैसे लोगों की मदद करने के लिए, यहां इसका जवाब है: "हमें डिलीट [] ऑपरेटर की भी आवश्यकता क्यों है?"


वापस आने और इसे अंदर डालने के लिए धन्यवाद।
Ziffusion

0

deleteएक एकल पॉइंटर के delete[]लिए उपयोग किया जाता है और एक पॉइंटर के माध्यम से एक सरणी को हटाने के लिए उपयोग किया जाता है। इससे आपको बेहतर समझने में मदद मिल सकती है।


-6

खैर .. शायद मुझे लगता है कि यह केवल स्पष्ट है। ऑपरेटर deleteऔर ऑपरेटर delete[]प्रतिष्ठित है, लेकिन deleteऑपरेटर सरणी को भी जारी कर सकता है।

test* a = new test[100];
delete a;

और पहले से ही चेक किए गए इस कोड का कोई मेमरी लीक नहीं है।

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