定义 NSMutableString?

发布于 2024-08-06 05:07:26 字数 494 浏览 8 评论 0原文

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

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

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

编辑...另外,

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

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

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

My understanding is that both of these create a NSMutableString, only the first one is owned by the system and the second one is owned by me (i.e. I need to release it). Is there any particular reason why I should use one or the other, on the face of it it seems easier to use the first? Also is the first better as it gives the compiler a sense of size?

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

OR

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

EDIT ... ALSO

I see a lot a declarations written on two lines (i.e.)

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

Personally I prefer the one-liner, is this just another example personal style?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不醒的梦 2024-08-13 05:07:26
NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

或者

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 的硬数字、来自 Instruments 的硬数字,还是只要循环运行足够长的时间,您的系统就会进入分页地狱)。

其他可能更好的解决方案包括将循环拆分为两个嵌套循环(外部循环为内部循环创建和耗尽自动释放池)并切换到 NSOperation。 (但是,请确保对队列一次运行的操作数设置限制,否则,您可能会更容易进入分页地狱。)

第一个是否更好,因为它为编译器提供了大小感?

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

对于编译器来说,这只是另一个类消息。编译器不知道也不关心它做了什么;对于它所知道和关心的一切,stringWithCapacity: 是向用户播放歌曲的消息。

它确实给了 NSMutableString 一个大小提示——类将知道它最初可能想要分配多少字符存储。无论您从中获得什么好处,都可能很小(至少在 Mac 上),但如果您手头有这些信息,为什么不使用它呢?相反,我不会特意去计算它。

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

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

我个人更喜欢俏皮话,这只是个人风格的另一个例子吗?

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

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

OR

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

Is there any particular reason why I should use one or the other, on the face of it it seems easier to use the first?

Yes. Always autorelease immediately unless you have a specific reason not to.

The first reason is that it's very easy to forget to write the release message. If you autorelease the object in the very same statement where you create it (as in [[[… alloc] init] autorelease]), it's much more difficult to forget it and much more obvious when you do. The convenience factory methods (such as stringWithCapacity:) autorelease the object for you, so just as when you autorelease it yourself, you don't have to worry about releasing it later.

Second, even if you do remember to write the separate release message, it's easy to not hit it. Two ways are early returns:

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

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

[str release];

and thrown or propagated exceptions:

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];

The “specific reason not to” is generally that you have a tight loop that creates a lot of objects, in which case you may want to manually manage as many of the objects in the loop as you can, in order to keep your object count down. However, only do this if you have evidence that this is your problem (be it hard numbers from Shark, hard numbers from Instruments, or your system going into paging hell whenever that loop runs long enough).

Other, possibly better, solutions include splitting the loop into two nested loops (the outer one to create and drain an autorelease pool for the inner loop) and switching to NSOperation. (However, make sure you set a limit on how many operations the queue runs at a time—otherwise, you may make it even easier to go into paging hell.)

Also is the first better as it gives the compiler a sense of size?

It is better, but not for that reason.

To the compiler, it's just another class message. The compiler does not know or care what it does; for all it knows and cares, stringWithCapacity: is the message to play a song to the user.

It does give NSMutableString a size hint—the class will know how much character storage it may want to initially allocate. Whatever benefit you get from this is probably small (at least on the Mac), but if you have the information handy, why not use it? Conversely, I wouldn't go out of my way to compute it.

I see a lot a declarations written on two lines (i.e.)

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

Personally I prefer the one-liner, is this just another example personal style?

Yes. However, there is a certain amount of risk in leaving a variable uninitialized. Definitely turn on the “Run Static Analyzer” build setting if you decide to make a habit of this.

魔法唧唧 2024-08-13 05:07:26

前者不一定是针对编译器的,而是向字符串提供关于如何优化其数据存储的建议。这对于 NSDictionary/NSArray/NSSet 最有用,它 能够在内部根据数据集的大小更改其实现

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

The former is not for the compiler necessarily, but rather a suggestion to the string as to how it might be able to optimize storing its data. This is most useful for NSDictionary/NSArray/NSSet, which have the ability to internally change their implementations depending on the size of their data set.

Other than that, you're correct: the only difference is a matter of ownership. I almost never use the WithCapacity methods, and rather just use [NSMutableString string] or [NSMutableArray array], but IMO, it's really just a matter of style and you won't gain or lose anything by using one over the other.

枕头说它不想醒 2024-08-13 05:07:26

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

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

我相信 2 行初始化只是样式,但我不会使用 2 行变体,因为您在定义变量时没有为其赋值,即使您在下一行。我猜这种镜像成员变量声明/初始化,但我个人不太喜欢它。

The first one is an autoreleased string. This will be released by the system at an appropriate point. It is added to the autorelease pool and memory will be handled by the system. Once it is out of scope, you cannot garuntee that it will be valid. This type is useful if it only has scope within your method, and also for returning values from methods.

The second is retained, so will have a reference count of 1 and is not added to the autorelease pool. You are responsible for releasing it and freeing up the memory. Use this method if you want to control the scope of the object. Used for member variables etc.

I believe the 2 line initialisation is just style, but I would not use the 2 line variation as you are defining the variable without assinging a value to it, even though you are on the next line. I guess this kind of mirrors member variable declaration/initialisation, but I dont personally like it much.

想你的星星会说话 2024-08-13 05:07:26

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

当您确实有充分的理由自己管理字符串的内存时,请使用第二个。例如您想确定何时应该清理字符串,或者您希望在某个时间内存最小。

我想说,作为一般规则,当你有充分的理由时,请使用第二个。

You bring up valid questions. It really depends on what you are doing but for general iPhone apps I would say just use the first one. This will be automatically cleaned up for you when the reference count gets to 0 and you don't have to worry about it.

Use the second one when you really have a good reason to manage the string's memory yourself. Such as you want to be sure of when the string should be cleaned up, or you expect memory to be minimal at a certain time.

I would say as a general rule use the second one when you have a good reason to do so.

美男兮 2024-08-13 05:07:26

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

我不确定大小/容量提示会产生多大的差异,但更多信息肯定应该允许运行时做出更好的决策。

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

当我第一次开始开发 iPhone 应用程序时,我一直使用自动释放的对象。这很方便,因为我并不完全理解它是如何工作的,而且它通常会做正确的事情。这些天我倾向于手动释放内存。当您真正了解引用计数的工作原理并在不了解时立即解决问题时,这实际上并不难。

You're correct on all your points!

I'm not sure how big a difference the size/capacity hint makes, but more information should certainly allow the run-time make better decisions.

Why use one style over the other? Well, when are autoreleased objects released? There are two non-obvious reasons why it might matter. First, when a method uses a lot of memory that you can release immediately. (You could also use a local autorelease pool I guess.) Secondly, I find that using autorelease can hide memory leaks and make debugging some code more difficult. Your mileage may vary depending on the age and quality of the code.

When I first started developing iPhone apps I used autoreleased objects all the time. It was convenient because I didn't fully understand how it all worked and it usually did the right thing. These days I tend to err on the side of manually deallocating memory. It really isn't that hard when you actually understand how the reference counting works and forces the issue immediately when you don't.

黑白记忆 2024-08-13 05:07:26

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

If you're pretty sure how long a string you'll need, go ahead and use the -initWithCapacity: method. When you exceed a string's storage, it gets reallocated and copied, which isn't a cheap operation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文