2009-07-25 10 views
13

यहां कोड है जिसका मैं उल्लेख कर रहा हूं।किसी ऑब्जेक्ट की बनाए रखने की गिनती क्या बढ़ जाती है?

// Person.h 

@interface Person : NSObject { 
    NSString *firstName; 
    NSString *lastName; 
} 
@end 

// Person.m 

@implementation Person 
- (id)init { 
    if (![super init]) return nil; 
    firstName = @"John"; 
    lastName = @"Doe"; 
} 
@end 

// MyClass.m 

@implementation MyClass 
    ..... 
- (NSArray *)getPeople { 
    NSMutableArray *array = [[NSMutableArray alloc] init]; 

    int i; 
    for (i = 0; i < 10; i++) { 
     Person *p = [[Person alloc] init]; 
     [array addObject:p]; 
    } 

    return array; 
} 
    ..... 
@end 

अब, मुझे पता है कि इस नमूना कोड में कोई मेमोरी-प्रबंधन नहीं चल रहा है। क्या आवश्यक होगा?

getPeople लूप में, मैं एक व्यक्ति (retainCount 1) आवंटित कर रहा हूं, फिर इसे सरणी में जोड़ रहा हूं। बरकरार गिनती अब 2 है, है ना? यदि यह दो है, तो क्या मुझे इसे सरणी में जोड़ने के बाद [पी रिलीज़] करना चाहिए, जिससे retainCount वापस 1 तक लाया जा सकता है?

क्या मैं सही हूं कि यह विधि द्वारा लौटाए गए सरणी को जारी करने के लिए कॉलर की ज़िम्मेदारी है? (जो व्यक्ति की यादों को भी मुक्त करेगा, और उनके उदाहरण चर, यह मानते हुए कि उनकी गणना 1 है)।

मैंने ऐप्पल के मेमोरी प्रबंधन दस्तावेज़ को पढ़ा है, लेकिन मुझे लगता है कि मैं सबसे अस्पष्ट हूं, क्या वस्तुओं को गिनती बरकरार रखती है? मुझे लगता है कि मैं इस विचार को समझता हूं कि रिलीज करना किसकी ज़िम्मेदारी है। यह मौलिक नियम है एप्पल के अनुसार:

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

बॉब डेविल की वाक्य "केवल उस आइटम को बनाए रखने के बारे में चिंता करें जिसे आप स्पष्ट रूप से आइटम में जोड़ते हैं" ने इसे मेरे लिए क्लिक किया। ऐप्पल में स्वामित्व नीति पढ़ने के बाद, अनिवार्य रूप से, ऑब्जेक्ट/विधि जिसने नई वस्तु बनाई है, वह इसे जारी करने/इसमें रुचि रखने के लिए ज़िम्मेदार है। क्या ये सही है?

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

यदि इनमें से कोई भी गलत है, तो मुझे बताएं।

उत्तर

18

आप सही है कि बनाए रखने गिनती एक सरणी में जोड़ने के बाद 2 है। हालांकि, आपको केवल उस आइटम को बनाए रखने के बारे में चिंता करनी चाहिए जो आप आइटम में स्पष्ट रूप से जोड़ते हैं।

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

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

Person *p = [[Person alloc] init]; //retain 1, for you 
[array addObject:p]; //array deals with p however it wants 
[p release]; //you're done, so release it 

इसके अलावा, जैसा कि मैंने ऊपर, केवल आप ही कहा ऑब्जेक्ट के दौरान ऑब्जेक्ट का स्वामित्व या आम तौर पर प्रतिलिपि बनाते हैं, इसलिए चीजों के दूसरी तरफ इसके साथ संगत होने के लिए, आपको सरलीकृत सरणी वापस करनी चाहिए, ताकि प्राप्त करने वाले लोगों के कॉलर का स्वामित्व न हो।

return [array autorelease]; 

संपादित करें: सही है, यदि आप इसे बनाने के लिए, आप इसे जारी करना होगा। यदि आप इसमें रुचि रखते हैं (बनाए रखने के माध्यम से) आपको इसे जारी करना होगा।

4

जब आप आवंटित कॉल को विशेष रूप से कॉल करते हैं तो बनाए रखें गिनती बढ़ जाती है, इसलिए आपको इसे स्पष्ट रूप से रिलीज़ करना होगा।

कारखाने के तरीके आमतौर पर आपको एक ऑटोरेलेज्ड ऑब्जेक्ट (जैसे [एनएसएमयूटेबलएरे ऐरे] देते हैं - आपको इसे किसी भी समय के लिए इसे रखने के लिए विशेष रूप से बनाए रखना होगा।)।

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

यदि आप अपने इवर्स को @property (retain) जैसे एंड्सचुवर जैसे गुणों के रूप में घोषित करते हैं, तो आप कुछ हद तक अंतर्निहित रह सकते हैं, और अपने कार्यान्वयन में @ सिंथेसाइज़ का उपयोग कर सकते हैं। संश्लेषण मूल रूप से आपके लिए सेटर्स और गेटर्स बनाता है, और यदि आप विशेष रूप से कॉल (रखरखाव) कहते हैं, तो सेटटर उस वस्तु को बनाए रखने के लिए जा रहा है।इसका हमेशा तुरंत स्पष्ट नहीं है, क्योंकि setters इस तरह संरचित किया जा सकता:

Person fart = [[Person alloc] init]; 
fart.firstName = @"Josh"; // this is actually a setter, not accessing the ivar 
          // equivalent to [fart setFirstName: @"Josh"], such that 
          // retainCount++ 

संपादित करें:

और जहाँ तक स्मृति प्रबंधन के रूप में, जैसे ही आप सरणी वस्तु जोड़ते हैं, आप कर रहे हैं इसके साथ किया ... इसलिए:

for (i = 0; i < 10; i++) { 
     Person *p = [[Person alloc] init]; 
     [array addObject:p]; 
     [p release]; 
    } 

जोश

2

आप चाहिए आम तौर पर/नहीं/बनाए रखने गिनती के बारे में चिंतित होना। यह आंतरिक रूप से लागू किया गया है। आपको केवल इस बात की परवाह करनी चाहिए कि क्या आप इसे बनाए रखने के द्वारा किसी ऑब्जेक्ट को "स्वामित्व" बनाना चाहते हैं। उपर्युक्त कोड में, सरणी को ऑब्जेक्ट का स्वामित्व होना चाहिए, न कि आप (उस लूप के बाहर जिसे आप सरणी के अलावा इसके संदर्भ में भी संदर्भित नहीं करते हैं)। क्योंकि आपके पास [[Person alloc] init] है, तो आपको इसे रिलीज़ करना होगा।

इस प्रकार

Person *p = [[Person alloc] init]; 
[array addObject:p]; 
[p release]; 

इसके अलावा, "getPeople" के फोन करने वाले सरणी ही नहीं करना चाहिए। यह सम्मेलन है। आपको इसे पहले ऑटोोरलीज करना चाहिए।

NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; 

आप स्मृति प्रबंधन पर एप्पल के प्रलेखन पढ़ने के लिए चाहता हूँ: http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

+0

जोश का कहना है कि एनएसएमयूटेबलएरे को डिफ़ॉल्ट रूप से ऑटोरेलीज़ के लिए चिह्नित किया गया है? –

+2

आपको अपने द्वारा बनाए गए ऑब्जेक्ट को स्पष्ट रूप से स्वतः ही करना होगा। – mjhoy

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

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