2008-08-26 12 views
8

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

मुझे वर्तमान में बढ़ावा देने की अनुमति नहीं है। मुझे शुद्ध सी ++ से चिपकना है क्योंकि मैं जिस फ्रेमवर्क का उपयोग कर रहा हूं वह जेनेरिक के किसी भी प्रयोग को रोकता है।

+0

बहुत बुरा यह इतना पुराना है। मुझे इस बारे में एक स्पष्टीकरण सुनना अच्छा लगेगा कि आप (विशेष रूप से) जेनेरिक क्यों नहीं उपयोग कर सकते हैं। – jmucchiello

+0

ढांचे के दस्तावेज़ीकरण से: टेम्पलेट का उपयोग न करें। वे विभिन्न ऑपरेटिंग सिस्टम के लिए पोर्टेबल नहीं हैं, विशेष रूप से जिस तरह से वे कंपाइलर्स और लिंक-एडिटर्स द्वारा समर्थित हैं। वर्तमान में मैं इसके बारे में कह सकता हूं –

+0

टेम्पलेट्स को 200 9 में विभिन्न ऑपरेटिंग सिस्टम पर ठीक से समर्थन दिया गया था, जब तक कि ओएस के पास उनके लिए मुश्किल सक्षम कंपेलर उपलब्ध थे। कोई भी ढांचा लिखने वाला व्यक्ति अपने दावे के लिए कुछ वास्तविक प्रमाणों के साथ आना चाहिए था। –

उत्तर

14

मैंने एम्बेडेड सिम्बियन ओएस के साथ काम किया है, जिसके लिए डेवलपर सम्मेलनों पर पूरी तरह से आधारित एक उत्कृष्ट प्रणाली थी।

  1. केवल एक ऑब्जेक्ट के पास एक सूचक होगा। डिफ़ॉल्ट रूप से यह निर्माता है।
  2. स्वामित्व पारित किया जा सकता है। स्वामित्व को पारित करने के लिए, ऑब्जेक्ट विधि हस्ताक्षर में एक सूचक के रूप में पारित किया जाता है (उदा। शून्य फू (बार * ज़ोंक);)।
  3. स्वामी यह तय करेगा कि ऑब्जेक्ट को कब हटाना है।
  4. किसी ऑब्जेक्ट को केवल उपयोग के लिए किसी ऑब्जेक्ट को पास करने के लिए, ऑब्जेक्ट विधि हस्ताक्षर में संदर्भ के रूप में पारित किया जाता है (उदा। शून्य फू (बैट & ज़ोंक);)।
  5. गैर-मालिक कक्षाएं ऑब्जेक्ट्स को संदर्भ (कभी पॉइंटर्स) स्टोर नहीं कर सकती हैं, जब वे निश्चित हो सकते हैं कि मालिक इसे उपयोग के दौरान नष्ट नहीं करेगा।

असल में, यदि कोई वर्ग बस कुछ उपयोग करता है, तो यह संदर्भ का उपयोग करता है। यदि किसी वर्ग के पास कुछ है, तो यह एक सूचक का उपयोग करता है।

यह खूबसूरती से काम करता था और इसका उपयोग करने में खुशी थी। मेमोरी के मुद्दे बहुत दुर्लभ थे।

+0

मैं यह दिखाने के लिए std :: auto_ptr <> का उपयोग करूंगा कि मालिक जहाज को स्थानांतरित किया जा रहा है (रॉ पॉइंटर के बजाए)। संभवतः आप एक स्मार्ट सूचक में पहले से ही स्टोर कर रहे हैं, अगर एकमात्र स्वामित्व की अपेक्षा की जाती है तो std :: auto_ptr <> सही है। –

+0

ओपी ने कहा कि वह जेनेरिक का उपयोग नहीं कर सका, जो किसी भी स्मार्ट सूचक प्रकार का अनुमान लगाता है। –

+0

यदि अनुप्रयोग द्वारा इंगित ऑब्जेक्ट गलती से हटा दिया गया है तो अनुप्रयोग कोर डंप नहीं होगा? यदि यह एक सूचक था, तो हम शून्य की जांच कर सकते थे। (बशर्ते डिलीटर इसे शून्य पर सेट करता है।) – balki

5

नियम:

  1. भी संभव हो, एक smart pointer का उपयोग करें। बूस्ट में good ones है।
  2. यदि आप स्मार्ट पॉइंटर का उपयोग नहीं कर सकते हैं, null out your pointer after deleting it
  3. कभी कहीं भी काम आप नियम 1.

का उपयोग किसी नियम 1 अनुमति नहीं देता है, तो नहीं दूँगा कि, याद रखें कि यदि आप किसी और के कोड हड़पने, चर नाम कॉपीराइट नोटिस बदल सकते हैं और, कोई हटाना कभी नोटिस होगा। जब तक यह एक स्कूल प्रोजेक्ट न हो, जहां तक ​​वे वास्तव में उस परिष्कृत उपकरणों के साथ उस तरह के शेंगेनियों की जांच नहीं करते हैं। यह भी देखें, this question

+0

-1। मैं यहां इस पर चर्चा नहीं करूंगा, लेकिन यह ** ** अच्छा अभ्यास नहीं है। यदि कोड काफी अच्छी तरह से लिखा गया है, तो यह आवश्यक नहीं होना चाहिए, क्योंकि इससे पहले कि आपको यह सुनिश्चित नहीं किया जाना चाहिए कि आपके आवंटित स्मृति ब्लॉक में कोई ** अन्य ** संदर्भ/पॉइंटर्स मौजूद नहीं हैं। –

0
  • आपके द्वारा प्रबंधित स्मृति मैन्युअल उपयोग करने के लिए है, तो सुनिश्चित करें कि आप एक ही गुंजाइश/समारोह/वर्ग/मॉड्यूल है, जो कभी पहले लागू होता है में हटाना फोन, जैसे बनाना:
  • एक के फोन करने वाले हैं फ़ंक्शन इसे भरने वाली मेमोरी आवंटित करता है, नए'ड पॉइंटर्स को वापस न करें।
  • हमेशा उसी एक्सई/डीएल में हटाएं जिसे आपने नया कहा है, क्योंकि अन्यथा आपको ढेर भ्रष्टाचार (विभिन्न असंगत रनटाइम लाइब्रेरी) में समस्या हो सकती है।
2

सामान्य मामले में (संसाधन प्रबंधन, जहां संसाधन आवश्यक स्मृति नहीं है), आपको RAII pattern से परिचित होना चाहिए।यह सी ++ डेवलपर्स के लिए जानकारी के सबसे महत्वपूर्ण टुकड़ों में से एक है।

0

आप कुछ आधार वर्ग कि कार्यक्षमता की तरह स्मार्ट सूचक लागू से सब कुछ प्राप्त कर सकता है (संदर्भ()/unref() तरीकों और एक काउंटर का उपयोग कर।

सभी @Timbo से प्रकाश डाला अंक रहे महत्वपूर्ण है जब कि आधार वर्ग को डिजाइन।

1

G'day,

मैं स्कॉट Meyers। आसान से "प्रभावी सी ++" के प्रासंगिक अनुभाग पढ़ने को पढ़ने के लिए सुझाव देंगे और वह जाल को कुछ रोचक gotchas असावधान को शामिल किया गया।

मैं भी चिंतित टेम्पलेट की कमी से। तो कोई एसटीएल या बूस्ट नहीं। वाह।

BTW सम्मेलनों पर सहमत करने के लिए लोगों रही एक उत्कृष्ट विचार है। जैसा कि सभी को ओओडी के लिए सम्मेलनों पर सहमत होना है। बीटीडब्ल्यू प्रभावी सी ++ के नवीनतम संस्करण में ओओडी सम्मेलनों के बारे में उत्कृष्ट अध्याय नहीं है कि पहले संस्करण में एक दयालुता थी, उदा। सार्वजनिक आभासी विरासत हमेशा मॉडल "आईएसए" संबंधों जैसे सम्मेलन।

रोब

3

मैं यहाँ एक और नियम जोड़ना होगा:

  • नया नहीं है/एक वस्तु जब एक स्वचालित वस्तु ठीक करना होगा हटा दें।

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

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

+0

नाइस से उठा रहा है" इससे उन्हें लगता है कि उन्हें चाहिए एक सूचक को "बनाने" के लिए (बहुत से लोगों को लगता है कि यह नया है) एक फ़ंक्शन में पॉइंटर पास करने में सक्षम होने के लिए।) "हो सकता है, लेकिन मुझे ऐसा लगता है क्योंकि ज्यादातर विश्वविद्यालय जावा को पहले सिखाते हैं। जावा में आपको सबकुछ" नया "करना होता है और आदत तोड़ना मुश्किल होता है, खासकर जब दोनों भाषाएं समान दिखती हैं, लेकिन वास्तव में पूरी तरह से अलग होती हैं। असली के लिए मजेदार, एक ही समय में दोनों के साथ काम करने का प्रयास करें! –

2

सामान्य रूप से, ढेर से आवंटित होने से बचें जब तक आपको यह करना न पड़े। यदि आपको, उन वस्तुओं के संदर्भ संदर्भ का उपयोग करना है जो लंबे समय तक रहते हैं और आपके कोड के विभिन्न हिस्सों के बीच साझा करने की आवश्यकता है।

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

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

इसके अलावा, डॉ। पिज्जा की तरह मुझे लगता है कि टेम्पलेट का उपयोग न करने का प्रतिबंध बहुत कठोर है। हालांकि, सोलारिस, एईक्स, और एचपी-यूएक्स के प्राचीन संस्करणों पर बहुत अधिक विकास करने के बाद (हाल ही में - हाँ, ये प्लेटफॉर्म अभी भी फॉर्च्यून 50 में जीवित हैं), मैं आपको बता सकता हूं कि यदि आप वास्तव में पोर्टेबिलिटी की परवाह करते हैं, तो आप जितना संभव हो सके टेम्पलेट का उपयोग करना चाहिए। कंटेनरों और स्मार्ट पॉइंटर्स के लिए उनका उपयोग करना ठीक होना चाहिए, हालांकि (यह मेरे लिए काम करता है)। टेम्पलेट्स के बिना मैंने जो तकनीक वर्णित की है वह लागू करने के लिए और अधिक दर्दनाक है। यह आवश्यक होगा कि "कलेक्टर" द्वारा प्रबंधित सभी ऑब्जेक्ट्स एक सामान्य बेस क्लास से प्राप्त हों।

+0

जबकि स्थानीय जीसी मुहावरे अच्छा लगता है, यह आवश्यक नहीं है। मैन्युअल मेमोरी प्रबंधन अच्छी तरह से करना मुश्किल नहीं है। –

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