免责声明
下面的讨论给出了一个关于为什么在 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。
您得到的是a 和b 是指向堆中同一个对象的两个指针。