2016-12-08 3 views
2

Почему следующие результаты NSLog отличаются?Почему значение указателя изменяется при передаче по ссылке?

UIView *view = [UIView new]; 
NSLog(@"%p",&view); //0x7fff59c86848 
[self test:&view]; 

-(void)test:(UIView **)view{ 
    NSLog(@"%p",view); // 0x7fff59c86840 
} 

В то время как следующие результаты NSLog одинаковы?

NSInteger j = 1; 
NSLog(@"%p", &j);//0x7fff5edc7ff8 
[self test1:&j]; 

- (void)test1:(NSInteger *)j{ 
    NSLog(@"%p", j);//0x7fff5edc7ff8 
} 

ответ

3

Хороший вопрос с неочевидным ответом.

Это связано с классификаторами собственности , связанным с переменными. При объявлении:

NSView *view; 

это сокращение для:

NSView __strong * view; 

т.е. ссылка прочно удерживаются переменной view.

Однако при объявлении:

-(void)test:(UIView **)view 

это сокращение для:

-(void)test:(UIView * __autoreleasing *)view 

view здесь имеет тип указатель на переменную указателя типа __autoreleasing к UIView.

Причина этой разницы, __strong против __autoreleasing, из-за какого вызова по обратной записи Apple, термина и объясняется в Variable Qualifiers in Apple's "Transitioning to ARC Release Notes" и в Ownership qualification in CLANG Documentation: Automatic Reference Counting. Также объясняются вопросы SO Handling Pointer-to-Pointer Ownership Issues in ARC и NSError and __autoreleasing.

Вкратце: указатель на __strong переменная не может быть передана как указатель на __autoreleasing. Чтобы поддержать это, компилятор вводит скрытую временную переменную и вместо этого передает свой адрес. То есть ваш код эффективно скомпилирован как:

UIView *view = [UIView new]; 
NSLog(@"%p",&view); 
UIView __autoreleasing * compilerTemp = view; 
[self test:&compilerTemp]; 
view = compilerTemp; 

Следовательно, почему вы видите другой адрес.

+0

Спасибо, ваш ответ действительно точным. Обратный инженерный результат работал, как вы говорите. И адреса в MRC одинаковы. – Zentopia

Смежные вопросы