2012-05-13 6 views
11

एक पुस्तक में, निम्नलिखित कहा गया है:उद्देश्य-सी में, स्वामित्व ऑब्जेक्ट के लिए है, परिवर्तनीय या पॉइंटर्स नहीं?

तो तुम कैसे जानते हो जब एक वस्तु के स्वामित्व में है, और किसके द्वारा? निम्न उदाहरण पर विचार करें:

NSString *str = [[NSString alloc] initWithString:@”Hello”]; 
NSString *str2 = str; 

इस उदाहरण में, आप str के लिए alloc कीवर्ड का उपयोग, तो आप खुद str। इसलिए, जब आपको इसकी आवश्यकता नहीं है, तो आपको इसे रिलीज़ करने की आवश्यकता है। हालांकि, str2 बस str पर इंगित कर रहा है, इसलिए आपके पास str2 का स्वामित्व नहीं है, जिसका अर्थ है कि को str2 रिलीज़ करने की आवश्यकता नहीं है जब आप इसका उपयोग कर रहे हैं।

मैंने सोचा था कि स्वामित्व वस्तु, चर नहीं या सूचक है ... इसलिए हम यह नहीं कह सकते कि हम "खुद str" या "खुद str2" ... हम एक वस्तु है, जो या तो द्वारा की ओर इशारा कर रहा है के मालिक हैं str या str2, और यदि हम [str release] या [str2 release] का उपयोग करते हैं, तो यह वही है।

अन्य वर्णन है:

उदाहरण के लिए, उदाहरण के पिछले अनुभाग में उपयोग किया जाता है पर विचार करें:

NSString *str = [[NSString alloc] initWithString:@”Hello”]; 
NSString *str2 = str; 
[str release]; 
[str2 release]; //---this is not OK as you do not own str2--- 

str2 जारी करने के लिए है क्योंकि आप एक मुक्त नहीं कर सकते एक रनटाइम त्रुटि में परिणाम होगा प्रयास कर रहा है वस्तु आपके स्वामित्व में नहीं है।

हम वास्तव में [str2 release] का उपयोग कर सकते हैं यदि इसे [str release] से पहले कहा जाता है। यदि हम ऐसा करते हैं, तो लाइन [str release] त्रुटि उत्पन्न करेगी क्योंकि अब str साथ ही str2 दोनों खतरनाक पॉइंटर्स हैं, और माना जाता है कि release ऑब्जेक्ट को पहली बार भेजा गया था, संदर्भ संख्या 0 हो गई, और dealloc तुरंत कॉल किया गया था, और स्मृति को सी फ़ंक्शन free() द्वारा मुक्त किया गया था।

क्या उपरोक्त सही है, या शायद कुछ और सुधारने के लिए है?

+2

+1, लेकिन नए कोड में [एआरसी] (http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-transitioningToARC/Introduction/Introduction.html) का उपयोग करने पर विचार करें। – rid

+0

+1, अच्छा सवाल, बीटीडब्ल्यू। –

+0

आप सही हैं। किताब या तो बहुत भ्रमित या गलत है। – Saphrosit

उत्तर

5

स्मृति प्रबंधन के संदर्भ में इसके बारे में मत सोचें, लेकिन ऑब्जेक्ट स्वामित्व के संदर्भ में। जब आप इसे आवंटित करते हैं, इसे बनाए रखते हैं, या इसे कॉपी करते हैं तो आप किसी ऑब्जेक्ट का स्वामित्व प्राप्त करते हैं। आप बिल्कुल सही वस्तुओं को जारी करने के लिए ज़िम्मेदार हैं, दूसरों के नहीं।

अपने उदाहरण में str2 असाइनमेंट वस्तु का स्वामित्व नहीं ले करता है, लेकिन अगर आप वास्तव में इसे करने के लिए एक दूसरे "मालिक" संदर्भ की आवश्यकता है, तो आप जिसके बाद यह [str release]; [str2 release]; ऐसा करने के लिए कोई त्रुटि नहीं है [str2 retain] करना चाहिए, । यह भी एआरसी का उपयोग करके स्वचालित रूप से होगा, जब तक कि आप कमजोर संदर्भ के रूप में str2 को एनोटेट नहीं करते। (निश्चित रूप से इस साधारण मामले में अनावश्यक बनाए रखने/रिलीज को संकलक द्वारा आंतरिक रूप से अनुकूलित किया जा सकता है।)

+0

यह एकमात्र बिल्कुल सही उत्तर है। –

0

यदि आप या तो str या str2 जारी करते हैं, तो स्मृति स्थान str और str2 अंक मुक्त है। इसलिए, आपको केवल str या str2 पर कॉल करना होगा, दोनों नहीं, क्योंकि वे एक ही स्मृति स्थान को इंगित करते हैं।

मुझे समझ में नहीं आता कि आप एक चर के मालिक के स्वामित्व से क्या मतलब रखते हैं, जहां तक ​​मुझे पता है कि एक सूचक सूचक में अंतरिक्ष के एक टुकड़े को इंगित कर सकता है, और कुछ भी नहीं।

+0

मैं "खुद का एक चर" वाक्यांश का उपयोग करता हूं क्योंकि लेखक यह सुझाव देते हैं कि हम "स्वयं 'str' हैं और 'str2' –

+0

नहीं हैं" ऑब्जेक्ट का स्वामित्व "की अवधारणा व्यापक रूप से प्रोग्रामिंग में उपयोग की जाने वाली ज़िम्मेदारी को संदर्भित करने के लिए उपयोग की जाती है एक वस्तु द्वारा कब्जा स्मृति में जगह। यदि आप किसी ऑब्जेक्ट के "स्वामित्व" हैं, तो आप इसकी स्मृति को साफ करने के लिए ज़िम्मेदार हैं। – rid

+0

इस तरह ... मुझे लगता है कि यह भ्रमित है, क्योंकि 'str2' ऑब्जेक्ट के साथ बिल्कुल वही कर सकता है जो इसे' str' can 'के रूप में इंगित करता है। अगर हम [str2 रिलीज] कहते हैं, तो इसका अर्थ है '[str रिलीज़]' जैसा ही है। यदि आप किसी ऑब्जेक्ट के निर्माण के लिए स्मृति में स्थान आरक्षित करने की क्रिया का जिक्र करते हुए 'स्वयं' का उपयोग कर रहे हैं, तो ऐसा लगता है कि एक सूचक के पास ऑब्जेक्ट पर अधिक शक्ति/विशेषाधिकार हैं। यह नहीं है, तो यह भ्रमित है। – Hidde

2

मैंने सोचा था कि स्वामित्व वस्तु, चर नहीं या सूचक है ... तो हम यह नहीं कह सकते कि हम "खुद str" या "खुद str2" ... हम एक वस्तु के मालिक हैं, जो है की ओर इशारा किया या तो str या str2 द्वारा, और यदि हम [str रिलीज़] या [str2 रिलीज़] का उपयोग करते हैं, तो यह वही है।

यह सही है।

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

+0

ऑब्जेक्ट को उस पॉइंटर का उपयोग करके स्मृति में रिलीज़ करना बेहतर क्यों होगा? दो पॉइंटर्स बराबर हैं, इसलिए पसंद आपकी है जिसे आप ऑब्जेक्ट को रिलीज़ करने के लिए उपयोग करना चाहते हैं। – Hidde

+1

एक बेहतर अवलोकन और समझने योग्य कोड के लिए। – DrummerB

+1

@ हिडे: यह तकनीकी रूप से कोई फर्क नहीं पड़ता है, लेकिन यदि आप इसका उपयोग करने में कुछ अनुशासन रखते हैं तो इसे बनाए रखने/रिलीज़ करने का ट्रैक रखना आसान हो जाता है। – fzwo

3

आपका अनुमान सही है: पुस्तक संकेत दूर को आसान बनाने के प्रयास में (भले ही निहितार्थ सही हैं) फजी भाषा का उपयोग:

आप वस्तु के मालिक हैं str और str2 बात करने के लिए कि।

निश्चित रूप से

इसका मतलब यह है कि आप केवल एक बार वस्तु जारी कर सकते हैं (या बल्कि लेकिन अक्सर यह बनाए रखा गया था - एक बार अपने उदाहरण में, परोक्ष, alloc द्वारा), और क्या आप str या str2 (या किसी भी अन्य साधनों के माध्यम से ऐसा कर) महत्वहीन है।

प्रैक्टिस में, आपको अपने चर के साथ व्यवहार करना चाहिए जैसे कि आप उनका स्वामित्व रखते हैं। यह बनाए रखने/रिलीज जोड़े को ट्रैक रखने के लिए बहुत आसान बनाता है, और आप इस तथ्य पर भरोसा नहीं कर सकते कि किसी ने कहीं भी इन चरों में से किसी एक के मूल्य को बदल दिया है।

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

तकनीकी जानकारी में एक सा गड्ढा करने के लिए (जो वास्तव में वे क्या कर रहे हैं के रूप में व्यवहार किया जाना चाहिए: कार्यान्वयन विवरण; एक निजी एपीआई की कलाकृतियों):

तकनीकी तौर पर, कोई भी नहीं वस्तु का मालिक है। इस ऑब्जेक्ट में कितनी बार बनाए रखा गया था (जिसे आप anObject retainCount पर कॉल करके पता लगा सकते हैं - लेकिन आपको कम से कम नहीं करना चाहिए क्योंकि कुछ ऑब्जेक्ट्स में एक फर्जी रीटैन काउंटर है, और क्योंकि यह वास्तव में आपकी कोई चिंता नहीं है)। जब कोई ऑब्जेक्ट alloc एड होता है, तो इसका रखरखाव गणना होता है 1. हर बार इसे retain ("इसे बनाए रखा जाता है") भेजा जाता है, इसकी रखरखाव गणना 1 तक बढ़ जाती है, और हर बार इसे release ("इसे जारी किया जाता है") भेजा जाता है, इसकी बरकरार गणना 1.

एक बार बनाए रखने के बाद किसी ऑब्जेक्ट की संख्या शून्य तक पहुंच जाती है, तो इसे हटा दिया जाता है (और इसकी dealloc विधि कहा जाता है)।

उन सभी retain/release संदेश (और किस चर के माध्यम से) महत्वपूर्ण नहीं है।

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

नोट: कुछ ऑब्जेक्ट्स (उदाहरण के लिए कुछ सिंगलेट्स) डिफ़ॉल्ट बनाए रखने/रिलीज़ विधियों को ओवरराइड करते हैं। जिज्ञासा के अलावा किसी ऑब्जेक्ट से retainCount पर भरोसा न करें (उदाहरण के लिए [UIColor clearColor] की रखरखाव की गणना करें)।

इस विषय पर अधिक विचारों के लिए, this question और इसके उत्तर शायद एक अच्छा सारांश/प्रारंभ बिंदु है।

ने कहा, एआरसी पर स्विच करने पर विचार करें, जो आपको लगभग सभी स्मृति प्रबंधन परेशानियों से छुटकारा दिलाएगा।

+0

स्वामित्व की अवधारणा वास्तव में संदर्भ गणना के बारे में तर्क करने का सही तरीका है, इसमें शामिल वास्तविक संख्या _not_ नहीं है। 'str' एक स्वामित्व संदर्भ है, और 'str2' एक ही ऑब्जेक्ट को इंगित करने के बावजूद नहीं है। 'रिलीज' को 'str2' पर भेजने के लिए यह अर्थपूर्ण रूप से गलत है क्योंकि आपने स्वामित्व-अनुदान विधि के माध्यम से उस संदर्भ को प्राप्त नहीं किया है। –

+0

@ जैक्स्यूस मुझे उम्मीद है कि मैंने यह स्पष्ट कर दिया है कि वास्तविक बनाए रखने काउंट एक उत्सुक कार्यान्वयन विस्तार के अलावा कुछ भी नहीं है। आप सही हैं कि वही चर के माध्यम से ऑब्जेक्ट्स को रिलीज़ करना सर्वोत्तम अभ्यास है (कम से कम क्योंकि गैर-तुच्छ उदाहरणों में से एक चर अब एक अलग ऑब्जेक्ट को इंगित कर सकता है); फिर भी, स्वामित्व "केवल" एक अवधारणा है, तकनीकी सत्य नहीं, IMHO। आपका बहुत अच्छा सवाल और उत्तर http://stackoverflow.com/questions/5784084/calling-retaincount- पर विचार किया गया- हानिकारक इस बारे में कुछ उत्सुकता भी पूरा कर सकता है। – fzwo

+0

ठीक है, आपने अपने उत्तर के दूसरे भाग को पूर्ववत किया है, जहां आप गणना को बनाए रखने के बारे में बात करते हैं और 'retainCount' का उपयोग करके" और भी सही पाने के लिए "का उपयोग करते हैं, जो यह नहीं है। संदर्भ गणना की "तकनीकी सत्य" है (जैसा कि आपने कहा था) उपयोगकर्ता की कोई भी चिंता नहीं - स्वामित्व उच्च स्तर है जहां अर्थ रहता है और निर्णय कहाँ किए जाने चाहिए। उस स्तर पर, यह बिल्कुल _does_ एक अंतर बनाता है जिसे आप 'रिलीज' भेजने के लिए उपयोग करते हैं। यह केवल निम्न स्तर पर है, जिसे आपको (आमतौर पर) अनदेखा करना चाहिए, कि आप अपने पसंदीदा संदर्भ के माध्यम से 'रिलीज' भेज सकते हैं। –

1

मुझे लगता है कि अन्य उत्तरों गलत हैं या अपूर्ण हैं।

स्वामित्व परिभाषित किया जाता है जो संसाधन जारी करता है। एक ऑब्जेक्ट (आमतौर पर) स्वयं नहीं है, यह स्वामित्व है।

फिर से: स्वामी जो भी स्मृति जारी करने के लिए जिम्मेदार है।

आपके कोड में, str ने ऑब्जेक्ट का अपना स्वामित्व घोषित कर दिया है, str2 नहीं है।

[str2 retain]; 

अब आप बाद में कह सकते हैं,

[str2 release]; 

त्यागना: आदेश के लिए str2 भी वस्तु के मालिक हैं करने के लिए (साझा करने के लिएstr के स्वामित्व), तो आपको retain के लिए यह आवश्यकता होगी स्वामित्व के str2 का दावा, और यह str के लिए जाता है।

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

दोहराने के लिए: स्वामित्व ऑब्जेक्ट द्वारा नहीं है। स्वामित्व पॉइंटर्स से एक ऑब्जेक्ट और उन पॉइंटर्स के मालिक द्वारा है, लेकिन यदि उन पॉइंटर्स को कुछ परिदृश्य में रिलीज़ किया जा सकता है। यदि कोई परिदृश्य नहीं है जिसमें वे संसाधन जारी करेंगे तो पॉइंटर्स गैर-स्वामित्व वाले हैं। इस मामले में, उन्हें कमजोर कहा जाता है।

कमजोर सूचक की अवधारणा का कोई अर्थ नहीं होगा यदि ऑब्जेक्ट्स स्वामित्व में हैं (क्योंकि सभी पॉइंटर्स कमज़ोर होंगे)।

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