2010-03-09 14 views
18

जब आप new [] का उपयोग करके एक सरणी आवंटित करते हैं, तो आप सूचक से उस सरणी का आकार क्यों नहीं ढूंढ सकते? इसे रन टाइम पर जाना जाना चाहिए, अन्यथा delete [] यह नहीं जान पाएगा कि कितनी मेमोरी मुक्त है।एक नए [] 'डी सरणी के आकार तक पहुंचना क्यों संभव नहीं है?

जब तक मुझे कुछ याद नहीं आ रहा है?

+0

एक साधारण अच्छे डिजाइन को जानने की आवश्यकता नहीं है - एक जटिल मामले में आपको अपने आप को बहुत प्रबंधन करना होगा। आपके कंपाइलर के लिए सामान्य डीबग फ़ंक्शन हैं जो आपको बताएंगे - लेकिन यदि आपको इसकी आवश्यकता है तो आपका डिज़ाइन शायद गलत है। –

+0

मैंने अक्सर सोचा है कि आप कभी भी आवंटन क्यों नहीं देखते हैं जो आकार को नहीं जानता है, और उसे हटाने पर पारित होने की आवश्यकता है। क्योंकि आप कितनी बार स्मृति के ब्लॉक को हटाने के लिए आए हैं और आसानी से इसकी आकार की गणना करने में सक्षम नहीं हैं? मुझे लगता है कि इस सीमा के साथ एक प्रणाली को लागू करने के लिए वास्तव में कभी लाभ नहीं होना चाहिए ... – matt

+0

यह शायद निम्न स्तर के संचालन के कार्यान्वयन पर अनावश्यक प्रतिबंध लगाएगा। आखिरकार आप जानते थे कि आपने सरणी आवंटित करने के लिए कितना पूछा था, इसलिए रनटाइम की कोई दिक्कत नहीं है कि आपको यह बताने में सक्षम हो। – UncleBens

उत्तर

14

एक सामान्य कार्यान्वयन में गतिशील मेमोरी ब्लॉक का आकार किसी भी तरह ब्लॉक में ही संग्रहीत होता है - यह सच है। लेकिन इस जानकारी तक पहुंचने का कोई मानक तरीका नहीं है। (कार्यान्वयन इसे एक्सेस करने के लिए कार्यान्वयन-विशिष्ट तरीकों को प्रदान कर सकता है)। यह malloc/free के साथ है, इस प्रकार यह new[]/delete[] के साथ है।

वास्तव में, एक विशिष्ट कार्यान्वयन में new[]/delete[] कॉल के लिए कच्चे स्मृति आवंटन अंत में कुछ कार्यान्वयन विशेष malloc/free तरह जोड़ी, जिसका अर्थ है delete[] वास्तव में कितनी स्मृति पुनःआवंटन करने के बारे में परवाह नहीं है कि द्वारा कार्रवाई की जाती है: बस इसे कॉल करता है कि आंतरिक free (या जिसे भी नाम दिया गया है), जो इसका ख्याल रखता है।

क्या delete[] हालांकि पता करने की जरूरत है स्थितियों में विनाश जब सरणी तत्व प्रकार गैर तुच्छ नाशक है कि कितने तत्वों है। और यह आपके प्रश्न के बारे में है - सरणी तत्वों की संख्या, ब्लॉक के आकार नहीं (ये दोनों समान नहीं हैं, ब्लॉक वास्तव में सरणी के लिए आवश्यक से बड़ा हो सकता है)। इस कारण से, सरणी में तत्वों की संख्या सामान्य रूप से ब्लॉक के अंदर new[] द्वारा संग्रहीत की जाती है और बाद में उचित सरणी तत्व विनाश करने के लिए delete[] द्वारा पुनर्प्राप्त किया जाता है। इस नंबर तक पहुंचने के लिए कोई मानक तरीका नहीं है।

(इसका मतलब यह है। कि सामान्य स्थिति में, एक ठेठ स्मृति new[] द्वारा आवंटित ब्लॉक स्वतंत्र रूप से, एक साथ दोनों शारीरिक ब्लॉक आकार बाइट्स और सरणी तत्व गिनती में स्टोर करेगा ये मान सी के विभिन्न स्तरों से जमा हो जाती है ++ मेमोरी आवंटन तंत्र - कच्चे मेमोरी आवंटक और new[] क्रमशः - और किसी भी तरह से एक-दूसरे से बातचीत नहीं करते हैं)।

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

ऊपर समझने के लिए, जब आप int रों

int *array = new int[100]; 

सरणी के आकार की एक सरणी बनाने के (यानी 100) नहीं सामान्य रूप से new[]delete[] के बाद से द्वारा संग्रहीत इसके बारे में परवाह नहीं करता (int है कोई विनाशक नहीं है)। बाइट्स (जैसे, 400 बाइट्स या अधिक) में ब्लॉक का भौतिक आकार सामान्य रूप से कच्चे मेमोरी आवंटक द्वारा ब्लॉक में संग्रहीत होता है (और delete[] द्वारा लगाए गए कच्चे मेमोरी डेलोकेटर द्वारा उपयोग किया जाता है), लेकिन यह आसानी से कुछ के लिए 420 हो सकता है कार्यान्वयन-विशिष्ट कारण। इसलिए, यह आकार मूल रूप से आपके लिए बेकार है, क्योंकि आप इससे सटीक मूल सरणी आकार प्राप्त नहीं कर पाएंगे।

+1

हां, स्मृति आवंटक सरणी के आकार को नहीं जानता है। हो सकता है कि यह अगले सबसे बड़े उपलब्ध आकार का एक ब्लॉक लौटा हो और यह भी ध्यान न दे कि आपने केवल 75% यह। –

7

आप शायद इसे एक्सेस कर सकते हैं, लेकिन इसके लिए आपके आवंटक के अंतरंग ज्ञान की आवश्यकता होगी और पोर्टेबल नहीं होगा। सी ++ मानक निर्दिष्ट नहीं करता है कि कार्यान्वयन इस डेटा को संग्रहीत करते हैं, इसलिए इसे प्राप्त करने के लिए कोई निरंतर विधि नहीं है। मेरा मानना ​​है कि यह अनिर्दिष्ट छोड़ दिया गया है क्योंकि विभिन्न आवंटक इसे दक्षता उद्देश्यों के लिए विभिन्न तरीकों से स्टोर करना चाहते हैं।

+0

फिर भी यह अच्छा होगा अगर मानक ने 'लेन (...)' ऑपरेटर निर्दिष्ट किया था, इसलिए उस ऑपरेटर का उपयोग करके सरणी का आकार प्राप्त करना संभव है (और लेखक उस लेन ऑपरेटर को लागू कर सकते हैं जैसे वे चाहते हैं)। .. :( – smerlin

+4

@smelin यह नहीं है कि 'std :: vector <>' क्या है? – KitsuneYMG

5

यह समझ में आता है, उदाहरण के लिए आवंटित ब्लॉक का आकार आवश्यक रूप से सरणी के समान आकार नहीं हो सकता है। जबकि it is true कि new[] तत्वों की संख्या (प्रत्येक तत्व विनाशक को बुलावा) स्टोर कर सकता है, ऐसा नहीं है क्योंकि इसे खाली विनाशक के लिए आवश्यक नहीं है। new[] लागू करने के लिए कोई मानक तरीका नहीं है (C++ FAQ Lite 1, C++ FAQ Lite 2) जहां new[] सरणी की लंबाई को संग्रहीत करता है क्योंकि प्रत्येक विधि में इसके पेशेवर और विपक्ष होते हैं।

दूसरे शब्दों में, यह कार्यान्वयन के बारे में कुछ भी निर्दिष्ट नहीं करके आवंटन को यथासंभव तेज़ सस्ता करने की अनुमति देता है। (यदि कार्यान्वयन को सरणी के आकार के साथ-साथ आवंटित ब्लॉक के आकार को हर बार स्टोर करना होता है, तो यह उस स्मृति को बर्बाद कर देता है जिसकी आपको आवश्यकता नहीं हो सकती है)।

3

बस शब्दों में कहें, सी ++ मानक को इसके लिए समर्थन की आवश्यकता नहीं है। यह संभव है कि यदि आप अपने कंपाइलर के आंतरिक के बारे में पर्याप्त जानते हैं, तो आप यह जान सकते हैं कि इस जानकारी को कैसे पहुंचाया जाए, लेकिन आमतौर पर खराब अभ्यास माना जाएगा। ध्यान दें कि ढेर-आवंटित सरणी और स्टैक-आवंटित सरणी के लिए मेमोरी लेआउट में कोई अंतर हो सकता है।

कि याद रखें आप अनिवार्य रूप से क्या यहाँ के बारे में बात कर रहे हैं सी-शैली सरणियों भी हैं - भले ही new और delete सी ++ ऑपरेटर हैं - और व्यवहार सी से प्राप्त होती है आप एक सी ++ "सरणी" है कि चाहते हैं आकार, आप एसटीएल (उदाहरण के लिए std :: वेक्टर, std :: डेक) का उपयोग करना चाहिए।

+0

हाँ, मैं आमतौर पर सी-स्टाइल सरणी का उपयोग नहीं करता - यह केवल एक सामान्य प्रश्न था (यदि यह था संभव) कई मामलों में कुछ स्मृति बचाता है। –

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