2016-08-19 6 views
6

अब मैं पॉइंटर से पॉइंटर द्वारा उलझन में हूं, भले ही मैंने Why does NSError need double indirection? (pointer to a pointer) और NSError * vs NSError ** और बहुत कुछ पढ़ा है।एनएसईआरआर/एनएसओब्जेक्ट पॉइंटर गुजरने वाले व्यवहार को समझ नहीं सकता

मैंने कुछ सोच की है और अभी भी कुछ प्रश्न हैं।

यहाँ मैं यह लिखा:

- (id)doSomethingWithObj:(NSObject *)obj error:(NSError *__autoreleasing *)error 
{ 
    NSLog(@"inside error address: %p", error); 
    id object = obj; 
    if (object != nil) 
    { 
     return object; 
    } 
    else 
    { 
     NSError *tmp = [NSError errorWithDomain:@"after" code:0 userInfo:nil]; 
     *error = tmp; 
     return nil; 
    } 
} 

लेकिन मैंने पाया कि दो लॉगिंग पते अलग-अलग हैं:

NSError *error = [NSError errorWithDomain:@"before" code:0 userInfo:nil]; 
NSLog(@"outside error address: %p", &error]; 
[self doSomethingWithObj:nil error:&error]; 

आदेश ऊपर NSError विधि का परीक्षण करने के लिए, मैं इस लिखा था। ऐसा क्यों है?

2016-08-19 19:00:16.582 Test[4548:339654] outside error address: 0x7fff5b3e6a58 
2016-08-19 19:00:16.583 Test[4548:339654] inside error address: 0x7fff5b3e6a50 

क्या वे समान नहीं होंगे क्योंकि यह एक साधारण मूल्य प्रति था? यदि वे अलग होना चाहिए, तो पॉइंटर को पॉइंटर को NSError इंस्टेंस पर इंगित करने का अंत कैसे हो सकता है?

+2

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

+1

लेकिन एनएसईआरर * __autoreleasing * एक पैटर्न है जो हर जगह प्रयोग किया जाता है और यह संकलक द्वारा अलग-अलग पहचाना और संभाला जाता है। – gnasher729

उत्तर

0

तो, पहली पंक्ति पर प्रारंभ करने के बाद, errorNSError ऑब्जेक्ट के लिए एक सूचक है।

पहले लॉग में, आप उस पते को लॉग कर रहे हैं जिस पर पॉइंटर आयोजित किया गया है। यह ऑपरेटर के & पते का प्रभाव है। वैसे भी, पता है कि कुछ ऐसा करने में पता चला है।

आप इसमें गुजर रहे हैं: पॉइंटर -> पॉइंटर -> nserror-object।

लेकिन doSomething के हस्ताक्षर में डबल इंडिक्रेशन पर ध्यान दें। ऑटोरेलीज़िंग एनोटेशन स्पॉट करना मुश्किल बनाता है, लेकिन इसकी NSError **

तो संकलक आपका पैरामीटर लेता है और इसे दो बार 'अनचाहे' लेता है।

यह पॉइंटर -> पॉइंटर -> nserror-object के रूप में शुरू होता है। फिर पहले संकेत के बाद यह पॉइंटर बन जाता है -> nserror-object। फिर दूसरे संकेत के बाद यह nserror-object बन जाता है।

एर्गो, आप दो अलग-अलग चीजों को लॉग कर रहे हैं। पहला nserror-object के सूचक का पता है। दूसरा नस्ल-ऑब्जेक्ट का पता ही है।

संपादित करें: @MANIAK_dobrii बताते हैं कि वस्तु को errorही पहले और बाद में मामले में अलग है द्वारा इशारा किया।

यह सच है। यदि कुछ ऐसा करने में कोई त्रुटि होती है तो यह किसी अन्य खंड में एक बिल्कुल नया NSError उदाहरण बनाता है। फिर यह error सूचक में वापस लोड करता है। यही कारण है कि आप दो अलग-अलग पते देखेंगे, इसके बाद error पॉइंटर पूरी तरह से किसी अन्य ऑब्जेक्ट को इंगित कर रहा है।

+0

मामला नहीं, त्रुटि पहले से ही NSError उदाहरण के लिए एक सूचक है, और त्रुटि उस सूचक के लिए एक सूचक है। बात यह है कि विधि कॉल से पहले और किसी भी तरह से वे अलग हैं। मुझे नहीं पता कि क्यों और मुझे लगता है कि वे वही थे। –

+0

@MANIAK_dobrii हां, मैं कह रहा हूं कि 'त्रुटि पहले से ही एनएसईआरआरआर उदाहरण के लिए एक सूचक है, और त्रुटि उस सूचक के लिए एक सूचक है'। लेकिन मुझे लगता है कि मैं तुम्हारा मुद्दा देखता हूं। हां, वे अलग हैं क्योंकि, विधि में, एक और एनएसईआरआरआर उदाहरण अन्य ब्लॉक में फैला हुआ है और पॉइंटर में लोड हो गया है। यह एक अलग वस्तु है। – ncke

+0

यह मामला भी नहीं है। @ gnasher729 ने सही सही उत्तर दिया। यह एआरसी चारों ओर गड़बड़ कर रहा है, मुझे इसके बारे में दो बिंदुओं के लिए __autoreleasing के आसपास कुछ clang दस्तावेज़ों में पढ़ने के बारे में याद है, तो इसे एक नज़र डालें। इसके अलावा, क्षमा करें, मैं "बाद (विधि कॉल)" में स्पष्ट नहीं था, मेरा मतलब कॉल के अंदर विधि कॉल के बाद था, यानी कॉल के दौरान। –

4

कॉलर में परिवर्तनीय प्रकार NSError* है। पते में NSError* * टाइप किया गया है। समारोह NSError* __autoreleasing * की उम्मीद है। इसलिए संकलक NSError* __autoreleasing प्रकार के एक छिपे हुए चर बनाता है, कॉल से पहले छिपे हुए चर में NSError* प्रतिलिपि बनाता है, और कॉल के बाद इसे वापस भेजता है ताकि __autoreleasing दाएं के अर्थशास्त्र प्राप्त हो सके।

+0

उत्कृष्ट जवाब! मैं वास्तव में भूल गया था कि उस तरह के क्लैंग दस्तावेज़ों में कुछ था। क्या आप विवरण पर पढ़ने के लिए कुछ सुझाव दे सकते हैं? –

+0

@ gnasher729 मुझे यकीन नहीं है कि कारण '__autoreleasing' से संबंधित है क्योंकि मैंने इसे दोबारा परीक्षण किया है: जब मैंने कीवर्ड' __autoreleasing' को हटा दिया, तो मुझे एक ही समस्या मिली - अंदर और बाहर पॉइंटर्स के लिए अलग-अलग पते। – Boris

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