为什么不需要解除引用NSString指针?

在这个例子中

NSString *message = @"Hello"; message = @"World"; 

如果message只是一个指针,为什么我不需要明确说出消息中的任何内容现在等于string或*message = @"World"; 喜欢在C?

免责声明

下面的讨论给出了一个总体思路,说明为什么你永远不会在Objective-C中取消引用指向对象的指针。 但是,关于NSString文字的具体情况,这不是现实中发生的事情。 虽然下面描述的结构仍然是正确的并且它可能以这种方式工作,但实际发生的是字符串文字的空间在编译时被分配,并且你得到它的地址。 这对于字符串文字是正确的,因为它们是不可变的和常量的。 为了提高效率,每个文字只分配一次。

事实上

 NSString * a = @"Hello"; NSString * b = @"Hello"; NSLog(@"%@ %p", a, a); // Hello 0x1f4958 NSLog(@"%@ %p", b, b); // Hello 0x1f4958 

原始答案

因为它会被翻译成

 message = [[NSString alloc] initWithUTF8String:"Hello"]]; 

这将归结为

 message = objc_msgSend(objc_msgSend(objc_getClass("NSString"), @selector(alloc)), @selector(initWithUTF8String:), "Hello"); 

现在,如果我们看一下objc_msgSend的签名

 id objc_msgSend(id theReceiver, SEL theSelector, ...) 

我们看到该方法返回一个id类型,在Objective-C中是对象类型。 但是如何定义id

 typedef struct objc_object { Class isa; } *id; 

id被定义为指向objc_object结构的指针。

所以最后@"string"将在一个函数调用中进行转换,该函数调用将生成一个指向对象的指针(如果你愿意的话,就是一个objc_object结构),这正是你需要分配给message

底线, 您指定指针,而不是对象

为了更好地阐明最后的概念,请考虑这一点

 NSMutableString * a = [NSMutableString stringWithString:@"hello"]; NSMutableString * b = a; [a setString:@"hola"]; NSLog(@"%@", a); // "hola" NSLog(@"%@", b); // "hola" 

如果您正在分配对象,则b将是a的副本,并且对a任何进一步修改都不会受到影响b

相反,你得到的是ab是指向堆中同一对象的两个指针。