对象是否真的通过Value传递,或者Objective C运行时是一个聪明的伎俩?

时间:2012-09-11 10:59:23

标签: objective-c parameter-passing

看看这个:

#import <Foundation/Foundation.h>

@interface ClassA : NSObject

-(NSString *) method1:(NSString*)str1;

@end

@implementation ClassA

-(NSString *) method1:(NSString*)str1
{
    NSLog(@"2. %@ at %p", str1, str1);
    str1 = @"foo";
    NSLog(@"3. %@ at %p", str1, str1);  
    return str1;
}

@end


int main(int argc, const char * argv[])
{

    @autoreleasepool {

        // insert code here...
        NSLog(@"Hello, World!");
        NSString *str = @"moo";
        NSLog(@"1. %@ at %p", str, str);
        ClassA *a = [[ClassA alloc] init];
        NSString *b = [a method1:str];
        NSLog(@"4. %@ at %p", str, str);
        NSLog(@"5. %@ at %p", b, b);
    }
    return 0;
}  

控制台日志是:

2012-09-11 17:03:16.160 passByValue[1559:403] Hello, World!
2012-09-11 17:03:16.162 passByValue[1559:403] 1. moo at 0x104c42248
2012-09-11 17:03:16.162 passByValue[1559:403] 2. moo at 0x104c42248
2012-09-11 17:03:16.163 passByValue[1559:403] 3. foo at 0x104c421e8
2012-09-11 17:03:16.163 passByValue[1559:403] 4. moo at 0x104c42248
2012-09-11 17:03:16.164 passByValue[1559:403] 5. foo at 0x104c421e8

注意str的地址是main函数,在重新分配str1之前,method1中str1的地址是相同的。这是否遵循传递值的原则?

是的,在控制权返回main之后,str的值和地址保持不变,遵循传递值的原则。

所以任何人都可以解释这一点,或者我们应该接受这样一个事实:str是通过值而不是通过引用传递的。

2 个答案:

答案 0 :(得分:3)

首先,“对象”不是Objective-C中的值。你不能有“对象”类型的表达式 - 如果你做了类似的事情,编译器会抱怨:

NSString foo;

相反,你只能拥有对象指针。您可以通过对象指针对对象执行所有操作。在您的代码中,strstr1等是对象指针变量。

除此之外,Objective-C确实总是按值传递。你的问题没有意义,因为“对象”没有被传递或分配。 (“对象”首先不是值。)在您的示例中,您的方法采用对象指针。

与pass-by-value一样,对局部变量的赋值不会影响外部代码。

答案 1 :(得分:1)

实际上,如果对象参数确实是按值传递的,那么你会看到完全相反的行为。正是因为它们被引用传递,str1mainmethod1的地址相同 - 您只有两个引用(str和{{1 }})到同一个指针。