在哪种情况下,我们需要在ARC下编写__autoreleasing所有权限定符?


118

我正在努力完成难题。

__strong是所有Objective-C可保留对象指针(如NSObject,NSString等)的默认值。这是一个强大的参考。ARC -release在范围的末尾与a 保持平衡。

__unsafe_unretained等于旧方法。它用于弱指针而不保留可保留对象。

__weak__unsafe_unretained与之类似,只是它是一个自动归零的弱引用,这意味着一旦释放引用的对象,指针将设置为nil。这消除了悬挂指针和EXC_BAD_ACCESS错误的危险。

但是究竟有什么__autoreleasing好处呢?我很难找到有关何时需要使用此限定符的实际示例。我相信这仅适用于期望指针指向的函数和方法,例如:

- (BOOL)save:(NSError**);

要么

NSError *error = nil;
[database save:&error];

在ARC下必须这样声明:

- (BOOL)save:(NSError* __autoreleasing *);

但这太模糊了,我想完全理解为什么。我发现的代码片段将__autoreleasing放在两颗星之间,这对我来说很奇怪。类型是NSError**(指向NSError的指针),那么为什么要放置__autoreleasing在星星之间而不是简单地放置在它们之间NSError**

另外,可能还有其他情况我必须依靠__autoreleasing


1
我有同样的问题,下面的答案并不完全令人信服...例如,为什么系统没有提供像您这样的__autoreleasing装饰器声明带有NSError **参数的接口,并且过渡到Arc发行说明说它们应该?例如,NSFileManager.h中所有这些例程中的任何一个?
爸爸

Answers:


67

你是对的。如官方文档所述:

__autoreleasing表示由引用(id *)传递并在返回时自动释放的参数。

所有这些内容在ARC过渡指南中都有很好的说明。

在您的NSError示例中,声明__strong暗含意味着:

NSError * e = nil;

将转换为:

NSError * __strong error = nil;

调用save方法时:

- ( BOOL )save: ( NSError * __autoreleasing * );

然后,编译器将不得不创建一个临时变量,设置为__autoreleasing。所以:

NSError * error = nil;
[ database save: &error ];

将转换为:

NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;

您可以通过__autoreleasing直接将错误对象声明为来避免这种情况。


3
不,__autoreleasing仅用于通过引用传递的参数。这是一种特殊情况,因为您有一个指向对象指针的指针。便利构造函数之类的情况并非如此,因为它们仅返回指向对象的指针,并且ARC自动处理该对象。
Macmade 2012年

7
为什么__autoreleasing限定词放置在星星之间,而不仅仅是NSError **的前面?这对我来说很奇怪,因为类型是NSError **。还是因为这试图表明指向的NSError *指针必须限定为指向自动释放的对象?
骄傲的会员

1
关于您的第一条评论的@Proud成员-这是不正确的(如果我理解正确)-请参阅下面的Glen Low答案。创建错误对象和分配给自动释放变量(你在通过了一个)的保存功能。此分配导致该对象在那时被保留并自动释放。save函数的声明使我们无法向其发送除自动释放变量以外的任何东西,因为这正是它所需要的-这就是为什么我们在尝试时会创建一个临时变量的原因。
科林2012年

2
那么,为什么Apple界面似乎都没有这个?例如,NSFileManager.h中的所有内容?
2013年

1
@Macmade:偶然地,我注意到您的答案已被编辑(通过stackoverflow.com/users/12652/comptrol),我的印象是,至少对您的第一个示例所做的更改(“隐式...将被转换为...)是错误的,因为__strong预选赛已经从二线到一线移动也许你可以检查。
马丁- [R

34

在评论中跟踪Macmade的回答和Proud Member的后续问题,(也将其发布为评论,但超过了最大字符数):

这就是为什么__autoreleasing的变量限定词放在两颗星之间的原因。

作为开头,使用限定符声明对象指针的正确语法是:

NSError * __qualifier someError;

编译器会原谅这一点:

__qualifier NSError *someError;

但这是不正确的。请参阅Apple ARC过渡指南(请阅读以“您应该正确修饰变量...”开头的部分)。

要解决当前的问题:双指针不能具有ARC内存管理限定符,因为指向内存地址的指针是指向原始类型的指针,而不是指向对象的指针。但是,在声明双指针时,ARC确实想知道第二个指针的内存管理规则。这就是为什么将双指针变量指定为:

SomeClass * __qualifier *someVariable;

因此,如果方法参数是双NSError指针,则数据类型声明为:

- (BOOL)save:(NSError* __autoreleasing *)errorPointer;

用英语说“指向__autoreleasing NSError对象指针的指针”。


15

明确的ARC规范

对于__autoreleasing对象,将使用原始语义保留,自动释放新指针并将其存储到左值中。

例如,代码

NSError* __autoreleasing error = someError;

实际上转换为

NSError* error = [[someError retain] autorelease];

...这就是为什么当您有一个参数时NSError* __autoreleasing * errorPointer,它起作用的原因,然后被调用的方法将把错误分配给,*errorPointer并且上面的语义将生效。

您可以__autoreleasing在其他上下文中使用它来将ARC对象强制进入自动释放池,但这并不是非常有用,因为ARC似乎只在方法返回时使用自动释放池,并且已经自动处理了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.