2011-06-10 8 views
8

मैंने ऐप्पल से मेमोरी मैनेजमेंट गाइड पढ़ा है और मुझे नहीं पता कि यह मामला कहां समझाया गया है ...ऑब्जेक्टिव-सी वास्तव में क्या करता है जब आप ऑब्जेक्ट घोषित करते हैं?

कई बार, विशेष रूप से कक्षा के उदाहरण को वापस करने के लिए कक्षा विधि लिखते समय, मैं शुरू करूंगा यह इस तरह से बाहर है, क्योंकि मैंने इसे देखा है, और यह काम करता है।

[नोट] यह कोड स्मृति से है - मैं इसे अद्यतन कर दूंगा जब मैं एक उदाहरण दिखाने के लिए घर आता हूं जो वास्तव में काम करता है (मैंने इसे स्पष्ट करने के लिए इसे बनाया है, लेकिन स्पष्ट रूप से मुझे इसे बनाने के लिए पर्याप्त रूप से याद नहीं है । कुछ है कि समझ में आता है ...

[संपादित करें] यहाँ मेरी वास्तविक तरीका है - निश्चित रूप से हर किसी को सही है कि मैं alloc जो मैं कर रहा हूँ बुला जाना चाहिए था

+ (id)player 
{ 
    Player *player = nil; 
    if ((player = [[[super alloc] initWithFile:@"rocket.png"] autorelease])) { 
    [player setProjectileType:kProjectileBullet]; 
     [player setProjectileLevel:1]; 
     [player setInvincible:YES]; 
     [player setEmitter:[CCParticleSystemQuad particleWithFile:@"exhaust.plist"]]; 
     [[player emitter] setPosition:ccp(0.0, player.contentSize.height/2)]; 
     [player addChild:player.emitter]; 
    } 
    return player; 
} 

तो क्या मैं प्रतिक्रियाओं से मिल गया है: * उदाहरण घोषित करने से मुझे एक मेमोरी लोकेशन में पॉइंटर मिल जाता है और एक्सकोड बताता है कि ऑब्जेक्ट कौन सा वर्ग होगा। * पॉइंटर को बहुत ज्यादा शून्य पर सेट करना बस इसे शून्य पर सेट करता है - इसे इसमें कचरा रखने से रोकता है (दाएं?) * चूंकि मैं उदाहरण को ऑटोरेलेज़ कर रहा हूं, इसलिए लौटाई गई ऑब्जेक्ट भी ऑटोरेलेज्ड है।

मुझे यह समझने में मदद करने के लिए धन्यवाद!

+4

कहां से कुछ कहने के लिए वैचारिक रूप से समान है, आपने उपरोक्त "किया?" आपके द्वारा यहां सूचीबद्ध कोड समझ में नहीं आता है, और मैं इसे काम करने की उम्मीद नहीं करता। –

+0

@Rob - ऊपर मेरा संपादन देखें; मैं आज रात वास्तविक कोड के साथ संपादित करूँगा। रोगी होने के लिए धन्यवाद। – Steve

उत्तर

11

क्या कोई यह समझा सकता है कि संकलक इसे देखता है तो क्या करता है?

DooDad* aDooDad = nil; 

तुम सच में क्या संकलक करता है में रुचि रखते हैं, जवाब है: संकलक स्थानीय चर aDooDad है, जो एक सूचक प्रकार है के लिए ढेर पर कुछ स्मृति आरक्षित होगा (यह आम तौर पर 64 है या प्रोसेसर के आधार पर आकार में 32 बिट्स)। उस पॉइंटर को तब nil (आमतौर पर 0x00..00) रखने के लिए प्रारंभ किया जाता है।

इस तरह का बयान:

  DooDad* aDooDad = [[DooDad alloc] init...]; 

सूचक चर aDooDad के उपयोग के उद्देश्य यह है कि आगे आवंटित किया जाता है (जो स्मृति का पता alloc द्वारा आरक्षित है) की स्मृति में पता स्टोर करने के लिए बनाता है।

तो, अंत में,

DooDad* aDooDad = nil; 

एक वस्तु है, बस एक चर जिनकी सामग्री DooDad प्रकार का ऑब्जेक्ट के पते के रूप में समझा जाता है की घोषणा नहीं है। इसलिए, इस तरह की घोषणा किसी अन्य घोषणा की तरह है, उदाहरण के लिए। int से 0 को प्रारंभ करते समय, ताकि बाद में आप इसे if कथन में कुछ मान असाइन कर सकें।

की तरह एक बयान: वस्तु जिसका पता aDooDad में संग्रहीत किया जाता करने के लिए संदेश doSomething भेजें:

[aDooDad doSomething]; 

तरह ऑब्जेक्टिव-सी क्रम प्रणाली द्वारा व्याख्या की है। यदि वह पता nil कोई संदेश नहीं भेजा गया है। दूसरी ओर, यदि आप dereference एक शून्य सूचक: *aDooDad आपको अपरिभाषित व्यवहार प्राप्त होगा।

पॉइंटर्स बहुत कम स्तर की सामग्री हैं। आशा है कि ये आपकी मदद करेगा।

2

सरल घोषित करने से आपको एक सूचक मिलता है जिसे आप बाद में उपयोग कर सकते हैं। कोई स्मृति आवंटित नहीं है।

सुनिश्चित नहीं है कि आपके द्वारा पोस्ट की गई विधि का इरादा क्या है, लेकिन यह कई स्तरों पर गलत लगता है। यह हमेशा, शून्य वापस आ जाएगा। जब तक यह एक प्रारंभिक विधि नहीं है, इसे [स्वयं init] कॉल नहीं करना चाहिए। यदि यह प्रारंभिक विधि है, तो इसे स्वयं को वापस कर देना चाहिए और "init ..."

+0

क्षमा करें, मैं इसे स्मृति से टाइप कर रहा हूं। मैं पॉइंटर घोषणा भाग को छोड़कर सटीक कोड के बारे में निश्चित नहीं हूं। मुझे पता है कि मैं 'आवंटन' नहीं कह रहा हूं, लेकिन सिर्फ 'init'। यह 'कोकोस 2 डी' प्रोजेक्ट का हिस्सा है और मेरी वास्तविक कक्षा' सीसीएसप्रेट 'का उप-वर्ग है, और' init' विधि 'initWithFile है: ' – Steve

+1

@Steve:' nil' मान पर' init' को कॉल करना एक नो-ऑप है , और निश्चित रूप से कुछ भी उपयोगी नहीं होगा। – geoffspear

4

यदि आप सी या सी ++ से परिचित हैं, तो वैरिएबल को दो तरीकों से, कॉल स्टैक पर स्थिर रूप से, या गतिशील रूप से ढेर पर बनाया जा सकता है। स्टैक पर बनाई गई परिवर्तनीय मेमोरी को पुनः दावा किया जाता है जब वर्तमान स्टैक फ्रेम गुंजाइश से बाहर हो जाता है, इसलिए आपको इसे बनाने या नष्ट करने के बारे में चिंता करने की आवश्यकता नहीं है। उद्देश्य-सी में, वस्तुओं हमेशा गतिशील रूप से बनाए गए हैं। Primitives (जैसे int, float, pointers, आदि), या तो स्थिर या गतिशील रूप से बनाया जा सकता है।

- (id)something { 

    NSObject myObject; // Illegal static object allocation 
    NSObject* myObject; // Legal primitive (pointer) static allocation 
    int myInt; // Legal primitive static allocation 
    int* myIntPtr; // Legal primitive (pointer) static allocation 
} 

तो जब आप कहते हैं कि DooDad* dodad = nil;, आप एक आदिम (एक doodad सूचक) बना रहे हैं स्टैक पर: उदाहरण के लिए। एक ढेर चर होने के नाते, आप alloc नहीं है या यह dealloc, आप alloc'ing या निम्न विधि में स्मृति के किसी भी dealloc'ing के बारे में चिंता नहीं करता, जैसे:

- (id)allStackVariables { 
    int myInt = 0; 
    float myFloat = 0.0f; 
    float* myFloatPtr = NULL; 
    NSObject* myObject = nil; 
} 

nil बस के लिए यह निर्धारित करना परिवर्तक की सामग्री को जो भी संकलक nil परिभाषित करता है, हेक्स में 0x000000 जैसा कुछ सेट करता है। DooDad* dooDad = nil; कहकर int myInt = 0;

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