2011-09-11 5 views
8

प्रारंभ करने में एक अच्छा तरीका है मैं 2 नए प्रश्न हैं:ढेर पर या ढेर पर संग्रहीत NSStrings हैं और क्या एक

1) इस लाइन पर विचार करें:

NSString *myString = [[NSString alloc] initWithString: @"Value"]; 

दो चीजें थे मैं सीखा, लेकिन मुझे पुष्टि चाहिए: जैसा कि मैंने सीखा, "आवंटन" संदेश इंगित करता है कि एनएसएसटींग का उदाहरण "ढेर" स्मृति में संग्रहीत किया जाएगा। मुझे यह भी समझा गया कि "चार्स" जैसे आदिम चर "स्टैक" मेमोरी में संग्रहीत हैं।

इसका मतलब यह है कि:

  • NSString के कहने ढेर स्मृति में संग्रहीत किया जाता है;
  • और इस ऑब्जेक्ट में iVar पॉइंटर (जब initWithString विधि को कॉल किया गया था) आदिम "वर्ण" की "वैल्यू" स्ट्रिंग में है, जो स्टैक मेमोरी में रहता है? यह वास्तविकता में कैसे काम करता है?

दूसरा सवाल सीधे संबंधित है और मेरे लिए एक व्यक्तिगत दुविधा का कारण बनता है (शायद इसलिए कि मैं एक बिंदु याद कर रहा हूँ): 2) दो दृष्टिकोण से कौन सा परामर्श और क्यों हैं ?:

NSString *myString = [[NSString alloc] initWithString: @"Value"]; 
NSString *myString = @"Value"; 

यदि मेरा पहला प्रश्न पुष्टि हो गया है, तो दोनों दृष्टिकोणों को "अंत में" बिंदुओं को स्टैक मेमोरी में संग्रहीत वर्णों को इंगित करना चाहिए। इसलिए मैं वास्तव में पहले विकल्प का उपयोग करने और बनाए रखने की गिनती से परेशान होने का उद्देश्य नहीं देखता हूं।

उत्तर

13

संक्षिप्त उत्तर: इस मामले में, दोनों पंक्तियों का एक ही परिणाम होता है स्ट्रिंग स्थिर को सीधे myString पर असाइन करना ठीक है।

लंबे समय तक जवाब:

ऐसा नहीं है कि ऑब्जेक्टिव-सी वस्तुओं के ढेर पर आवंटित किए जाते हैं सच है। यह सच नहीं है, हालांकि, "आदिम" मान हमेशा ढेर पर संग्रहीत होते हैं। स्थानीय चर ढेर पर संग्रहीत होते हैं, भले ही वे आदिम हों या नहीं। (उदाहरण के लिए, एक स्थानीय चर एक struct, जो आदिम नहीं माना जाता है कि घोषणा कर सकते हैं।) आप ढेर पर आदिम मान संग्रहीत कर सकते, लेकिन इस मामले में उन तक पहुँचने के लिए एक ही रास्ता एक सूचक के माध्यम से है। उदाहरण के लिए:

int *someInt = malloc(sizeof(int)); // allocate a block of memory to hold an int 
*someInt = 42;      // store data in that memory 

कारण यह है कि हम हमेशा उपयोग संकेत ऑब्जेक्टिव-सी वस्तुओं का उल्लेख करने के कि वस्तुओं हमेशा ढेर पर आवंटित कर रहे हैं। यदि आप स्टैक पर कुछ स्टोर करना चाहते हैं, तो कंपाइलर को इसके आकार को जानने की जरूरत है। उद्देश्य-सी में, किसी ऑब्जेक्ट का आकार तब तक ज्ञात नहीं होता जब तक कि प्रोग्राम वास्तव में चल रहा न हो।

तो, अपने तारों पर वापस जाएं। निम्नांकित दो पंक्तियों को क्रियान्वित करने का प्रयास करें:

NSString *foo = [[NSString alloc] initWithString:@"foo"]; 
NSString *bar = @"foo"; 

आप दूसरी पंक्ति के बाद तोड़ हैं, तो आप पाएंगे कि foo और bar एक ही पते होते हैं; यानी, वे एक ही वस्तु को इंगित करते हैं। चूंकि एनएसएसटींग ऑब्जेक्ट्स अपरिवर्तनीय हैं, इसलिए एक स्थिर स्ट्रिंग वाला एक बनाना केवल उस पॉइंटर को स्थिर करता है।

क्यों भी NSString में एक -initWithString: अगर है कि सभी यह करता है? एनएसएसटींग एक "क्लास क्लस्टर" है, जिसका कहना है कि एनएसएसटींग कई अलग-अलग आंतरिक वर्गों के लिए सार्वजनिक इंटरफ़ेस है। यदि आप एक NSString * पार कर लेते हैं कि -initWithString: में एक निरंतर नहीं है, वस्तु आप वापस पाने के लिए जब आप निरंतर का उपयोग आप क्या मिलेगा तुलना में एक अलग वर्ग का एक उदाहरण हो सकता है। ताकि आप यह कैसे काम करता है सब के बारे में चिंता किए बिना तार के विभिन्न प्रकार के लिए अच्छा प्रदर्शन प्राप्त एक वर्ग क्लस्टर के रूप में, NSString आप से कार्यान्वयन विवरण का एक बहुत छुपाता है।

4

NSString एस दिलचस्प हैं क्योंकि वे हाल ही में एकमात्र प्रकार का उद्देश्य-सी ऑब्जेक्ट था जिसे शाब्दिक के रूप में प्रदान किया जा सकता था। आईओएस 4 और ओएस एक्स 10.6 में जोड़े गए ब्लॉक ऑब्जेक्ट्स हाल ही में जोड़े गए हैं जिन्हें मैं जानता हूं, लेकिन उनके पास अपने विशेष नियम हैं इसलिए मैं केवल पूर्णता के लिए उल्लेख करता हूं।

सी प्राइमेटिव ढेर या ढेर पर संग्रहीत किया जा सकता है। उदाहरण के लिए:

- (void)someMethod 
{ 
    int i = 3; // i is on the stack 
} 

- (void)someOtherMethod 
{ 
    int *i = (int *)malloc(sizeof(int)); // i now points to an 'int' on the heap 
} 

अधिकांश उद्देश्य-सी ऑब्जेक्ट केवल ढेर पर संग्रहीत किए जा सकते हैं। आपको यह कहने का काफी अधिकार है कि alloc ढेर पर किसी ऑब्जेक्ट की एक नई प्रति प्रस्तुत करता है, और आपके myString कॉल का परिणाम ढेर पर एनएसएसटींग को पॉइंटर होना होगा।

हालांकि, @"" सिंटैक्स ऑब्जेक्ट बनाने के लिए शॉर्टेंड है। @"Value" वास्तव में एक वस्तु शाब्दिक बनाता है। तो, उदाहरण के लिए, आप कर सकते हैं:

NSLog(@"%@", [@"Value" substringFromIndex:1]); 

और आउटपुट 'अल्यू' होगा। आप substringFromIndex: संदेश @"Value" पर भेज सकते हैं क्योंकि यह एक शाब्दिक वस्तु है।

सटीक रूप से NSStringinitWithString: के साथ एक कार्यान्वयन विशिष्ट है लेकिन आप निश्चित हो सकते हैं कि यह उस चीज की प्रतिलिपि लेगा जब इसकी आवश्यकता हो। नहीं तो आप अजीब व्यवहार यदि आप कुछ इस तरह किया था चाहते हैं:

NSMutableString *mutableString = [NSMutableString stringWithString:@"String"]; 
NSString *immutableString = [NSString stringWithString:mutableString]; 

[mutableString appendString:@" + hat"]; 

// immutableString would now have mutated if it was simply 
// keeping a reference to the string passed in 

इसलिए कुछ भी के जीवनकाल में आप इसे करने के लिए पारित के बारे में चिंता की जरूरत नहीं है। इससे निपटने के लिए NSString का काम है।

प्रैक्टिस में, NSString ऑब्जेक्ट लीटरल वास्तव में कभी समाप्त नहीं होते हैं, इसलिए बिंदु थोड़ा सा मूक है। यदि आप initWithUTF8String: या कुछ और जो सी शाब्दिक लेते हैं, और सी शाब्दिक स्टैक पर था, तो आपके पास अभी भी चिंता करने की कोई बात नहीं है क्योंकि NSString इससे निपटेंगे।

आपके दूसरे प्रश्न के उत्तर में, मैं इस आधार पर दूसरे संस्करण का पक्ष लेगा कि यह छोटा है और इसलिए अधिक स्पष्ट रूप से प्रदर्शित करता है कि आप क्या करना चाहते हैं। उत्तरार्द्ध के लिए कुछ सैद्धांतिक प्रदर्शन लाभ हैं - विशेष रूप से यदि आप कई स्थानों पर एक ही शाब्दिक उपयोग करते हैं - लेकिन वे आजकल विचार करने योग्य नहीं हैं, इसलिए वे इतने अविश्वसनीय रूप से नगण्य हैं।