在示例中
NSString *message = @"Hello";
message = @"World";
如果消息只是一个指针,为什么我不需要明确说明消息中的任何内容现在等于字符串或{C}中的*message = @"World";
?
答案 0 :(得分: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
是指向堆中同一对象的两个指针。