7

在示例中

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

如果 message 只是一个指针,为什么我不需要明确地说 message 中的内容现在等于 string 或*message = @"World";类似于 C 中的内容?

4

1 回答 1

14

免责声明

下面的讨论给出了一个关于为什么在 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指向堆中同一个对象的指针。

于 2013-04-09T17:47:52.357 回答