定义NSMutableString?

时间:2009-09-28 15:33:16

标签: objective-c cocoa nsmutablestring

我的理解是这两个都创建了一个NSMutableString,只有第一个由系统拥有,第二个由我拥有(即我需要释放它)。是否有任何特殊原因我应该使用其中一个,从表面看它似乎更容易使用第一个?也是第一个更好的,因为它给编译器一个大小的感觉?

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

OR

NSMutableString *newPath = [[NSMutableString alloc] init];

编辑......还

我看到很多声明写在两行(即。)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

我个人更喜欢单行,这只是个人风格的另一个例子吗?

6 个答案:

答案 0 :(得分:16)

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];
     

OR

NSMutableString *newPath = [[NSMutableString alloc] init];
     

为什么我应该使用其中一个,有什么特别的原因,从表面看它似乎更容易使用第一个?

是。除非您有特殊原因,否则请立即自动发布。

第一个原因是忘记编写release消息很容易。如果你在创建它的同一个语句中自动释放对象(如在[[[… alloc] init] autorelease]中),那么忘记它会更加困难,当你这样做时更加明显。便利工厂方法(例如stringWithCapacity:)会为您自动释放对象,因此就像您自己自动释放它一样,您不必担心以后会释放它。

其次,即使你确实记得写下单独的release消息,也很容易不打它。两种方式是早期回报:

NSString *str = [[NSString alloc] initWithString:@"foo"];

BOOL success = [str writeToFile:path atomically:NO];
if (!success)
    return;

[str release];

抛出或传播的异常:

NSString *str = [[NSString alloc] initWithString:@"foo"];

//Throws NSRangeException if str is not in the array or is only in the array as the last object
NSString *otherStr = [myArray objectAtIndex:[myArray indexOfObject:str] + 1];

[str release];

“没有特定原因”通常是你有一个创建大量对象的紧密循环,在这种情况下你可能想要手动管理循环中的尽可能多的对象,以便保持你的对象倒计时了。但是,只有在你有证据证明这是你的问题时才会这样做(无论是来自Shark的硬数字,来自乐器的硬数字,还是你的系统进入分页地狱,只要该循环运行的时间足够长)。 / p>

其他可能更好的解决方案包括将循环分成两个嵌套循环(外部循环创建并为内循环排出自动释放池)并切换到NSOperation。 (但是,请确保对队列一次运行的操作数设置限制 - 否则为you may make it even easier to go into paging hell。)

  

也是第一个更好的,因为它给编译器一个大小的感觉?

它更好,但不是因为这个原因。

对于编译器来说,它只是另一个类消息。编译器不知道或不关心它做什么;尽管它知道并关心,stringWithCapacity:是向用户播放歌曲的信息。

它确实为 NSMutableString 提供了一个大小提示 - 该类将知道它最初可能想要分配多少字符存储空间。你从中获得的好处可能很小(至少在Mac上),但如果你有方便的信息,为什么不使用它呢?相反,我不会忘记计算它。

  

我看到很多声明写在两行(即。)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];
     

我个人更喜欢单行,这只是个人风格的另一个例子吗?

是。但是,保留未初始化变量存在一定的风险。如果您决定养成这种习惯,请务必打开“运行静态分析器”构建设置。

答案 1 :(得分:4)

前者不一定是编译器,而是字符串建议如何能够优化存储其数据。这对于NSDictionary / NSArray / NSSet最有用,have the ability to internally change their implementations depending on the size of their data set

除此之外,你是对的:唯一的区别是所有权问题。我几乎从不使用WithCapacity方法,而只是使用[NSMutableString string][NSMutableArray array],但IMO,这只是一个风格问题,你不会通过使用一个来获得或失去任何东西在另一方面。

答案 2 :(得分:2)

第一个是自动释放的字符串。这将由系统在适当的时候发布。它被添加到自动释放池中,内存将由系统处理。一旦超出范围,您就不能认为它是有效的。如果此类型仅在方法中具有范围,并且还用于从方法返回值,则此类型非常有用。

第二个被保留,因此引用计数为1并且不会添加到自动释放池中。您有责任释放它并释放内存。如果要控制对象的范围,请使用此方法。用于成员变量等。

我认为2行初始化只是样式,但我不会使用2行变量,因为你定义变量而不给它赋值,即使你在下一行。我想这种镜像成员变量声明/初始化,但我个人并不喜欢它。

答案 3 :(得分:1)

你提出了有效的问题。这真的取决于你在做什么,但对于一般的iPhone应用程序,我会说只使用第一个。当引用计数达到0并且您不必担心时,这将自动清除。

当你真的有充分的理由自己管理字符串的内存时,请使用第二个。比如你想确定什么时候应该清理字符串,或者你希望记忆在某个时间内保持最小。

我会说,一般情况下,当你有充分的理由时,请使用第二个。

答案 4 :(得分:1)

你的所有观点都是正确的!

我不确定大小/容量提示有多大差异,但更多信息肯定会让运行时做出更好的决策。

为什么使用一种风格而不是另一种风格?好吧,什么时候发布了自动释放的对象?有两个非显而易见的原因可能是重要的。首先,当一个方法使用大量内存时,你可以立即释放。 (我猜你也可以使用本地自动释放池。)其次,我发现使用自动释放可以隐藏内存泄漏并使调试某些代码更加困难。您的里程可能会根据代码的年龄和质量而有所不同。

当我第一次开始开发iPhone应用程序时,我一直使用自动释放的对象。这很方便,因为我没有完全理解它是如何工作的,它通常是正确的。这些天我倾向于在手动释放内存方面犯错误。当你真正了解引用计数是如何工作的时候并没有那么难,当你不这样做时立即强制解决问题。

答案 5 :(得分:0)

如果您非常确定需要多长时间的字符串,请继续使用-initWithCapacity:方法。当你超过一个字符串的存储空间时,它会被重新分配和复制,这不是一个便宜的操作。