【问题标题】:Difference between these two NSString methods这两个 NSString 方法之间的区别
【发布时间】:2011-10-26 08:42:07
【问题描述】:

所以我今天在一次采访中被问到这个问题,经过一些谷歌搜索后仍然无法找出答案(事实上我什至找不到任何使用 [NSString string] 方法的代码)。

有什么区别

  1. NSString *someString = [NSString string];
  2. NSString *someString = [[NSString alloc] init];

现在我最初的想法是[NSString string] 将返回一个自动释放的对象,而使用 alloc 和 init 将返回一个已保留的对象。然而,这个答案似乎是不正确的。

我查看了苹果文档中的 NSString 类参考,但它所说的只是

Returns an empty string.

+ (id)string 

Return Value
An empty string.

谁能给我解释一下这两者之间的区别是什么?

【问题讨论】:

  • 如果这是你没有得到这份工作的唯一原因,这似乎有点不公平。
  • 在 iOS5(带有 ARC)中它们是相同的东西。
  • @jrturton 这只是我被问到的众多问题之一,我认为这不是我是否继续通过这个面试阶段的唯一原因

标签: iphone objective-c ios nsstring class-cluster


【解决方案1】:

这是您的回答吗?您是否问过为什么您的回答不正确?我问是因为你的假设大部分是正确的(在更高的层次上)。

alloc+init 返回时,它并不完全“保留”,它是一个您持有一个引用的对象,应该与releaseautorelease 保持平衡。对于方便的构造函数 (+[NSString string]),您将返回一个您持有零引用的对象,但除非您向其发送显式保留(假设 MRC 或 ARC,因为它被标记为 iOS)。

在较低级别,您可以做出一些猜测,但我不希望在许多 objc 采访中出现这个问题(除非您告诉他们您是中级或高级)。基本上,它是由实现定义的,但两种形式都可以返回相同的静态常量NSString(这可能是面试官正在寻找的)。举例说明:

@implementation NSString

static NSString * const EmptyNSString = @"";

- (id)init
{
    self = [super init];
    [self release];
    return EmptyNSString;
}

+ (id)string
{
    return EmptyNSString;
}

...

同样,这是定义的实现,但显然是优化。此外,这种优化使得可变变体 (NSMutableString) 的物理子类化具体不可变类型 (NSString) 变得困难在某些情况下

【讨论】:

  • 感谢贾斯汀的回复,我实际上并没有问这是否不正确,因为我们的面试时间有点短,但他们问我是否确定我的回答是正确的让我再看一遍这个问题,我疑惑地看了他们一眼,然后我们继续前进。
  • @Jason 啊,好的。所以这个问题可能得到了满意的回答,也可能没有得到满意的回答,他们想知道你是否知道我概述的优化(或者其他什么)。
  • @JeremyP 为什么不呢? ...或者你指的是我在编辑中澄清的一点?
  • @Justin:请参阅我的答案,了解为什么不这样做。但是,在重读您的答案时,我认为我的反对票很严厉,所以我将其删除。
  • @JeremyP 好吧,有几点我在此过程中措辞不佳,并在我意识到这一点后更新......
【解决方案2】:

现在我最初的想法是[NSString string] 会返回一个自动释放的对象

从技术上讲,它是一个恒定的占位符字符串,即它存在于整个程序执行过程中,永远不会被释放。它不是自动释放的字符串。从概念上讲,这是我作为面试官所关注的,它是一个不属于调用者的字符串(一个空字符串),因此调用者不应该释放它。

而使用 alloc 和 init 将返回一个已保留的对象

从技术上讲,它是一个恒定的占位符字符串,即它存在于整个程序执行过程中。其实和上面那个是同一个对象,没有保留。从概念上讲,这是我作为面试官所关注的,它是一个字符串(一个空字符串),由调用者拥有,因此调用者有责任在不再需要它时释放它。

【讨论】:

  • 由于这是一个关于面试的问题,我将其标记为正确答案,因为它似乎可以解释面试官期望的答案。谢谢变态
【解决方案3】:

正确答案是

NSString *someString = [NSString string];

给你一个你不拥有并且你不能释放的空字符串(根据内存管理规则)

NSString *someString = [[NSString alloc] init];

给你一个你拥有并且你必须释放的空字符串(根据内存管理规则)。

如果不深入实施,您就不能对这两个字符串说 任何其他内容。你不能说它们是自动释放的,因为它们可能不是,你不能说保留计数是多少。

实际上,您可能会(在这两种情况下)获得指向某个 NSString 子类的常量对象的相同指针,可能保留计数为 UINT_MAX,运行时将其用作禁用标志常量字符串的正常保留释放行为。我实际上并没有尝试过上述方法,因为除了 Objective-C SDK 的维护者之外没有人需要关心。

【讨论】:

  • 感谢 Jeremy 的回复并让我知道 UINT_MAX 标志
  • @Jason:UINT_MAX 是一个实现细节。你通常不需要知道它。
  • 是的,我明白这一点,但也许这只是我的一个小烦恼,但我想知道这些你通常不会从阅读教科书中学到的复杂的小细节
【解决方案4】:

你不经常看到

NSString *someString = [NSString string]; 

因为是一样的

NSString *someString = @""; 

哪个更短。它通常用于创建一个空的 NSMutableString

NSMutableString* s = [NSMutableString string];

【讨论】:

  • 这两个语句实际上是否具有完全相同的含义,背景中没有发生有趣的事情?我问是因为我很好奇为什么 NSString 类会有一个永远不会实际使用的字符串方法?
  • 注意+[NSString string]返回的常量空字符串和@""不是同一个对象。
  • 在 NSMutableString* s = [NSMutableString string]; 的情况下很有用
  • 投反对票的人能否解释一下 NSString *someString = [NSString string]; 的任何情况实际上与 NSString *someString = @""; 的行为不同
  • [NSString string] 是一个自动释放的空字符串,@"" 也是如此(无论如何你可以这样想,即使“技术上”,“在引擎盖下”,它也不是案例,这是一个实现细节)。
【解决方案5】:

我唯一能想到的是:

  1. 不会分配内存,因为它不是使用 alloc 生成的。是系统生成的常量(空字符串),不需要释放。

  2. 您自己为 NSString 分配内存,这意味着您必须跟踪完成后 NSString 是否仍然“存在”,因此需要释放它。

【讨论】:

  • 即使+[NSString alloc] 也不分配内存——它返回一个NSPlaceholderString 类型的占位符单例。这是实现类集群时的常见模式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 1970-01-01
  • 2014-06-02
  • 2018-06-12
  • 2011-09-19
  • 2020-11-19
相关资源
最近更新 更多