2

这可能是一个愚蠢的问题,但它一直困扰着我。

假设我们有一个将NSString对象作为参数并对该NSString对象执行某些操作的方法,

- (void)someMethod:(NSString *)str
{
    //do something with str
}

考虑这段代码

[someObject someMethod:[[NSString alloc] initWithFormat:@"Hello World!"]];

由于alloc已用于创建字符串作为 someMethod 的参数,因此release无论是在 pre-ARC 环境中显式还是在 ARC 下隐式都必须对其进行平衡。但似乎我们无法获得指向字符串的指针,因为我们从未将它分配给任何指针。

所以我的问题是,首先,在编写目标 c 代码时是否禁止这种传递参数的方式?如果不是,那么以这种方式创建的对象如何被释放?最后,这段代码会导致内存泄漏吗?


仅作记录,我理解上面的代码是写的

NSString *string = [[NSString alloc] initWithFormat:@"Hello World!"];
[someObject someMethod:string];
// [string release]; depending on ARC or non-ARC
4

3 回答 3

2

好吧,事实上,该对象分配给名为 的变量str,这是您的方法的一个参数。您可以通过该指针管理方法内部的内存,尽管方法不应该拥有其参数的所有权(见下文)。

ARC 知道在这种情况下该怎么做——它要么自动释放对象,要么在方法完成后添加释放。

在 MRR 下,您的代码段将是泄漏;避免这种情况的正确方法也是发送autorelease

[someObject someMethod:[[[NSString alloc] initWithFormat:@"Hello World!"] autorelease]];

或使用您的最后一个片段(将字符串放入临时变量并稍后释放)。

ns_consumed作为一个稍微深奥的选项,您的方法可以通过使用属性声明它拥有参数:

- (void)someMethod:(NSString *) __attribute__((ns_consumed)) str;

这表明你的方法应该release在它返回之前发送给对象——ARC 也会处理这个问题。

于 2013-06-28T20:35:24.837 回答
1

所以我的问题是,首先,在编写目标 c 代码时是否禁止这种传递参数的方式?

不,这是完全合法的。

如果不是,那么以这种方式创建的对象如何被释放?

ARC 会为您解决。如果你自己做引用计数,那么你可以在它超出范围之前将它添加到自动释放池中:

[someObject someMethod:
  [[[NSString alloc] initWithFormat:@"Hello World!"] autorelease]];
                                                     ^^^^^^^^^^^

最后,这段代码会导致内存泄漏吗?

不在ARC中。在 MRC 中,您需要添加-autorelease.

静态分析器也会指出泄漏。

于 2013-06-28T20:34:40.833 回答
0

当您要求考虑时,没有理由不编写代码……丝毫没有被禁止的东西。这些对象的释放方式与任何其他对象的释放方式相同。您缺少将指针存储在顶层的变量并不重要,因为 Objective C 运行时知道该对象。

于 2013-06-28T20:32:06.840 回答