最近看到一篇Objective-C中的值传递和引用传递文章,做下记录
零、结论先行:
在Objective-C中,对象作为参数传递给方法A时,该方法A会收到对象指针的副本(浅复制)。也就是说,被调用的方法A接收对象指针的副本,而调用的方法B保留对象的原始指针,且这两个指针指向同一个对象。
一、正式开始:
先看代码:
- (void)viewDidLoad {
[super viewDidLoad];
NSString *str = @"HelloWorld";
NSLog(@"调用前 str=%@,对象地址=%p,指针地址=%p \n",str,str,&str);
[self changeMyStr:str];
NSLog(@"调用后 str=%@,对象地址=%p,指针地址=%p \n",str,str,&str);
};
- (void)changeMyStr:(NSString *)str {
NSLog(@"方法执行前 str=%@,对象地址=%p,指针地址=%p \n",str,str,&str);
str = @"Nihao";
NSLog(@"方法执行后 str=%@,对象地址=%p,指针地址=%p \n",str,str,&str);
}
执行结果:
调用前 str=HelloWorld,对象地址=0x106705130,指针地址=0x310967878
方法执行前 str=HelloWorld,对象地址=0x106705130,指针地址=0x3109677b0
方法执行后 str=Nihao,对象地址=0x1067051b0,指针地址=0x3109677b0
调用后 str=HelloWorld,对象地址=0x106705130,指针地址=0x310967878
可以看到,str的值并不会改变。从结果看出:
①在调用前和赋值方法执行前,str指向的对象地址是一致的,说明指向同一个对象;但是指针地址不一致,说明调用前的str指针和参数的str指针不是同一个,即它们是两个指针,只是都指向了同一个对象。
②在赋值方法执行前和执行后,str指向的对象地址不一致,说明str指向了一个新的对象(即@"Nihao")
以下是该过程的模型解释:
二、更进一步:
在Objective-C中,OC方法的本质是消息转发,当编译器遇到Objective-C消息传递表达式时,会自动的转换成objc_msgSend对应的调用。比如,上述[self changeMyStr:str],会转换成objc_msgSend(self, @selector(changeMyStr:), str)。Objective-C方法的传参规则可以用C语言的函数传参规则来理解。
如有谬误,欢迎斧正,共同进步