声明
以下讨论概括了为什么在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
是对象类型。但是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);
NSLog(@"%@", b);
如果你在赋值对象,b
会是 a
的一个副本,对 a
的进一步修改不会影响到 b
。
而实际上你得到的是 a
和 b
是指向堆上同一个对象的两个指针。
@"World"
给出了字符串字面量的地址,所以message=&...
。 - Anoop Vaidya[[[NSString alloc] initWithUtf8String:"Hello"]] autorelease]
的一种捷径。 - Hot Licks