Objective-C的函数NSString参数传递

4,244 阅读2分钟

最近看到一篇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语言的函数传参规则来理解。

如有谬误,欢迎斧正,共同进步