2010-06-30 25 views
26

अंदर अपने मूल्य लौटने के बाद एक सूचक को हटाने के लिए कैसे मैं इस समारोह है:एक समारोह

char* ReadBlock(fstream& stream, int size) 
{ 
    char* memblock; 
    memblock = new char[size]; 
    stream.read(memblock, size); 
    return(memblock); 
} 

समारोह हर बार जब मैं एक फ़ाइल से बाइट्स पढ़ने के लिए कहा जाता है। मुझे लगता है कि हर बार जब मैं इसका इस्तेमाल करता हूं तो यह नई मेमोरी आवंटित करता है लेकिन सरणी के अंदर डेटा संसाधित करने के बाद मैं स्मृति को कैसे मुक्त कर सकता हूं? क्या मैं इसे फ़ंक्शन के बाहर से कर सकता हूं? बड़े ब्लॉक आवंटित करके डेटा प्रोसेसिंग डेटा के छोटे ब्लॉक आवंटित करने और हटाने से बेहतर प्रदर्शन देता है?

आपकी मदद के लिए बहुत बहुत धन्यवाद!

+8

+1। यह एक बड़ा सवाल है! यह मैन्युअल मेमोरी आवंटन के लिए बहुत से नए आने वालों को रोकता है। – Anthony

+0

यह एक भयानक सवाल है, नए आने वालों को 'std :: string' या 'std :: vector' का उपयोग करना सीखना चाहिए। –

+5

@ मैट्टीयू: सीखने के बजाय std :: string और std :: वेक्टर हुड के नीचे कैसे काम करता है? मुझे लगता है कि यह एक अच्छा सवाल है, हालांकि मैं पक्षपातपूर्ण हो सकता हूं क्योंकि यह एक है जो मैं खुद को रखता हूं, क्योंकि मैं यह जानने के बिना यादृच्छिक पुस्तकालयों का उपयोग करना नहीं चाहता हूं कि वे क्या कर रहे हैं। – abelito

उत्तर

15

गतिशील सरणियों delete[] का उपयोग कर रहे रिहा:

char* block = ReadBlock(...); 
// ... do stuff 
delete[] block; 

आदर्श रूप में हालांकि आप स्मृति प्रबंधन को यहाँ का उपयोग नहीं करते:

std::vector<char> ReadBlock(std::fstream& stream, int size) { 
    std::vector<char> memblock(size); 
    stream.read(&memblock[0], size); 
    return memblock; 
} 
+2

इस विधि के साथ, जब वेक्टर ऑब्जेक्ट लौटाया जाता है, तो क्या इसकी कॉपी कन्स्ट्रक्टर को कॉल किया जाता है (मेरा मतलब है, दो बिंदु एक बिंदु पर मौजूद हैं)? – dreamlax

+4

@ ड्रीम: यह निर्भर करता है, सबसे अधिक संभावना * नाम वापसी मूल्य अनुकूलन *, [एनआरवीओ] (http://en.wikipedia.org/wiki/Return_value_optimization), इसमें शामिल होगा। दिलचस्प भी देखें [स्पीड स्पीड? मूल्य से गुजरें।] (Http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/)। –

+0

@ जॉर्ज: दिलचस्प पोस्ट, लेकिन _very_ भ्रामक नाम। यह लगभग लगता है जैसे वे पास-दर-संदर्भ के बजाय पास-दर-मूल्य बहस कर रहे हैं। लिंक चारा, मुझे लगता है। – Stephen

5

बस delete[] जब आप इसके साथ समाप्त कर चुके हैं तो इस समारोह से वापसी मूल्य। इससे कोई फर्क नहीं पड़ता कि आप इसे बाहर से हटा रहे हैं। इसका उपयोग करने से पहले इसे हटाएं।

+2

इसे 'हटाएं'], 'हटाएं' नहीं होना चाहिए। –

+1

ओच! दुख की बात यह है कि यदि आप यह गलती करते हैं, तो संकलक इसे भी पहचान नहीं सकता है। क्या एक भयानक भाषा है। कोई बात नहीं धन्यवाद। मैं पोस्ट ठीक कर दूंगा। (हालांकि यह कहा जाना चाहिए, मैं वास्तव में कोड की पूरी लाइन का प्रस्ताव नहीं दे रहा था, बस इसका उपयोग करने के लिए क्या बनाया गया था।) – sigfpe

1

हां। आप फ़ंक्शन के बाहर से हटा सकते हैं। हालांकि, इस मामले में, क्या मैं एक std :: स्ट्रिंग का उपयोग करने का सुझाव दे सकता हूं ताकि आपको प्रबंधन के बारे में चिंता न करें?

+0

ठीक है, लेकिन मैं पढ़ने के कारण तारों का उपयोग नहीं कर सकता। istream और पढ़ें (char * s, streamsize n); – Emer

+0

फिर इसके बजाय वेक्टर का उपयोग करें। क्षमा करें, उस पर ध्यान नहीं दिया। –

4

आप कर सकते हैं कॉल:

char * block = ReadBlock(stream, size); 
delete [] block; 

लेकिन ... कि कोई लाभ के लिए ढेर आवंटन का एक बहुत कुछ है। इस दृष्टिकोण

char *block = new char[size]; 
while (...) { 
    stream.read(block, size); 
} 
delete [] block; 

* नोट लेने का विचार करें, अगर size एक संकलन समय निरंतर किया जा सकता है, तो आप सिर्फ आवंटित block ढेर कर सकते हैं।

+0

फ़ंक्शन में स्थिर पॉइंटर पास करने पर ठोस कॉल। +1 –

+1

परिवर्तनीय आकार के सरणी आईएसओ सी ++ नहीं हैं, यह एक जीसीसी विस्तार है। –

+0

@ वाह: कौन कहता है आकार संकलित समय नहीं है? – Stephen

1

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

जो फस्ट्रीम रीड फ़ंक्शन के फ़ंक्शन स्ट्रक्चर के प्रकार के साथ लाभ है। यह स्पष्ट रूप से स्पष्ट है कि वह कार्य जो करने जा रहा है वह आपके द्वारा प्रदान किए गए बफर में बाइट्स की 'आकार' संख्या पढ़ा जाता है, इससे कोई फर्क नहीं पड़ता कि बफर को नए का उपयोग करके आवंटित किया गया है, चाहे वह स्थिर या वैश्विक बफर हो या फिर भी एक स्थानीय बफर, या यहां तक ​​कि एक स्थानीय संरचना के लिए सिर्फ एक सूचक। और यह भी स्पष्ट रूप से स्पष्ट है कि यह कार्य उस डेटा को पढ़ने के बाद आपके द्वारा पारित बफर के साथ और कुछ नहीं करने जा रहा है।

दूसरी तरफ, अपने रीडब्लॉक फ़ंक्शन की संरचना लें; अगर आपके पास कोड नहीं था तो यह पता लगाना मुश्किल होगा कि यह वास्तव में क्या लौट रहा था। क्या यह नई याददाश्त के लिए एक सूचक वापस कर रहा है? यदि ऐसा है तो क्या आप इसे हटाने की उम्मीद कर रहे हैं? क्या यह इसे हटा देगा यह स्वयं है? अगर ऐसा हैं तोह कब? क्या यह भी एक नया सूचक है? क्या यह सिर्फ कुछ साझा स्थिर बफर को पता भेज रहा है? यदि हां, तो बफर कब अमान्य हो जाएगा (उदाहरण के लिए, किसी और चीज द्वारा ओवरराइट किया गया)

रीडब्लॉक को कोड देखकर, यह स्पष्ट है कि यह नई स्मृति में पॉइंटर लौटा रहा है, और आपको हटाने की उम्मीद है जब कभी आप इसके साथ किया जाता है। जब तक आप इसे हटा नहीं देते तब तक बफर कभी ओवरराइट नहीं किया जाएगा या अमान्य हो जाएगा।

गति के अनुसार, fsream.read के दूसरे लाभ को आप 'बफर' सॉर्ट आउट करते हैं: स्मृति आवंटित होने पर आपको पसंद मिलती है। यदि आप जा रहे हैं "डेटा पढ़ना, प्रक्रिया, बफर हटाएं, डेटा प्रक्रिया को बफर हटाएं, ect ...." यह केवल एक बफर आवंटित करने के लिए अधिक कुशल होगा (अधिकतम आकार के लिए आपको इसकी आवश्यकता होगी, यह होगा आपके सबसे बड़े एकल पढ़ने का आकार) और स्टीफन द्वारा सुझाए गए अनुसार, सब कुछ के लिए इसका उपयोग करें।

0

एक स्थिर चार * memblock का उपयोग करने के बारे में कैसे; इसे केवल एक बार शुरू किया जाएगा और यह हर बार एक नई जगह memblock आवंटित नहीं करेगा।

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