【问题标题】:Why dereferencing a NSString pointer is not necessary?为什么不需要取消引用 NSString 指针?
【发布时间】:2013-04-01 06:08:08
【问题描述】:

在示例中

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

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

【问题讨论】:

  • 因为@"World" 给出了字符串文字的地址。作为message=&...
  • @"Hello" 在概念上是[[[NSString alloc] initWithUtf8String:"Hello"]] autorelease] 的快捷方式。
  • ...因为@"World" 也是一个指针? ;)

标签: objective-c c nsstring


【解决方案1】:

免责声明

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

【讨论】:

  • 我喜欢你的底线。让它加粗......这样我就可以给你+1 :)
  • 确实值得大胆。
  • @"Hello" 这样的字符串文字被编译成二进制文件,它们不会被翻译成alloc:initWithUTF8String
  • @DanZimm 是的,我的意思是坚持常规的对象生命周期。很明显,最后这只是 C,因此您可以轻松地在堆栈上拥有任何结构。但是我几乎不怀疑任何 API 都可以在该对象上工作 ;)
  • 为堆栈对象制作一个严格的 api ;D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 2012-08-22
  • 2020-11-08
  • 2013-03-28
相关资源
最近更新 更多