ios 在哪些情况下我们需要在 ARC 下编写 __autoreleasing 所有权限定符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8862023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In which situations do we need to write the __autoreleasing ownership qualifier under ARC?
提问by Proud Member
I'm trying to complete the puzzle.
我正在努力完成拼图。
__strong
is the default for all Objective-C retainable object pointers like NSObject, NSString, etc.. It's a strong reference. ARC balances it with a -release
at the end of the scope.
__strong
是所有 Objective-C 可保留对象指针(如 NSObject、NSString 等)的默认值。这是一个强引用。ARC 用-release
范围末尾的a 来平衡它。
__unsafe_unretained
equals the old way. It's used for a weak pointer without retaining the retainable object.
__unsafe_unretained
等于旧方式。它用于不保留可保留对象的弱指针。
__weak
is like __unsafe_unretained
except that it's an auto-zeroing weak reference meaning that the pointer will be set to nil as soon as the referenced object is deallocated. This eliminates the danger of dangling pointers and EXC_BAD_ACCESS errors.
__weak
就像__unsafe_unretained
除了它是一个自动归零弱引用之外,这意味着一旦被引用的对象被释放,指针就会被设置为 nil。这消除了悬空指针和 EXC_BAD_ACCESS 错误的危险。
But what exactly is __autoreleasing
good for? I'm having a hard time finding practical examples on when I need to use this qualifier. I believe it's only for functions and methods which expect a pointer-pointer such as:
但究竟有什么__autoreleasing
好处呢?我很难找到有关何时需要使用此限定符的实际示例。我相信它仅适用于需要指针指针的函数和方法,例如:
- (BOOL)save:(NSError**);
or
或者
NSError *error = nil;
[database save:&error];
which under ARC has to be declared this way:
在 ARC 下必须以这种方式声明:
- (BOOL)save:(NSError* __autoreleasing *);
But this is too vague and I'd like to fully understand why. The code snippets I find place the __autoreleasing inbetween the two stars, which looks weird to me. The type is NSError**
(a pointer-pointer to NSError), so why place __autoreleasing
inbetween the stars and not simply in front of NSError**
?
但这太含糊了,我想完全理解为什么。我发现的代码片段将 __autoreleasing 放在两颗星之间,这对我来说看起来很奇怪。类型是NSError**
(指向 NSError 的指针),那么为什么要放在__autoreleasing
星星之间而不是简单地放在 前面NSError**
呢?
Also, there might be other situations in which I must rely on __autoreleasing
.
此外,可能还有其他情况我必须依赖__autoreleasing
.
采纳答案by Macmade
You're right. As the official documentation explains:
你是对的。正如官方文档解释的那样:
__autoreleasing to denote arguments that are passed by reference (id *) and are autoreleased on return.
__autoreleasing 表示通过引用 (id *) 传递并在返回时自动释放的参数。
All of this is very well explained in the ARC transition guide.
所有这些都在ARC 转换指南中得到了很好的解释。
In your NSError example, the declaration means __strong
, implicitly:
在您的 NSError 示例中,声明意味着__strong
,隐式:
NSError * e = nil;
Will be transformed to:
将转化为:
NSError * __strong error = nil;
When you call your save
method:
当你调用你的save
方法时:
- ( BOOL )save: ( NSError * __autoreleasing * );
The compiler will then have to create a temporary variable, set at __autoreleasing
. So:
然后编译器必须创建一个临时变量,设置为__autoreleasing
。所以:
NSError * error = nil;
[ database save: &error ];
Will be transformed to:
将转化为:
NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;
You may avoid this by declaring the error object as __autoreleasing
, directly.
您可以通过__autoreleasing
直接将错误对象声明为,来避免这种情况。
回答by Binyamin Bauman
Following up on Macmade's answer and Proud Member's follow up question in the comments, (would have also posted this as a comment but it exceeds the max character count):
在评论中跟进 Macmade 的回答和 Proud Member 的跟进问题,(也可以将此作为评论发布,但它超过了最大字符数):
Here is why the variable qualifier of __autoreleasing is placed between the two stars.
这就是为什么 __autoreleasing 的变量限定符放在两颗星之间的原因。
To preface, the correct syntax for declaring an object pointer with a qualifier is:
作为序言,使用限定符声明对象指针的正确语法是:
NSError * __qualifier someError;
The compiler will forgive this:
编译器会原谅这一点:
__qualifier NSError *someError;
but it isn't correct. See the Apple ARC transition guide(read the section that begins "You should decorate variables correctly...").
但这是不正确的。请参阅Apple ARC 转换指南(阅读以“您应该正确装饰变量...”开头的部分)。
To address to the question at hand: A double pointer cannot have an ARC memory management qualifier because a pointer that points to a memory address is a pointer to a primitive type, not a pointer to an object. However, when you declare a double pointer, ARC does want to know what the memory management rules are for the second pointer. That's why double pointer variables are specified as:
解决手头的问题:双指针不能有 ARC 内存管理限定符,因为指向内存地址的指针是指向原始类型的指针,而不是指向对象的指针。然而,当你声明一个双指针时,ARC 确实想知道第二个指针的内存管理规则是什么。这就是为什么双指针变量被指定为:
SomeClass * __qualifier *someVariable;
So in the case of a method argument that is a double NSError pointer, the data type is declared as:
因此,在方法参数是双 NSError 指针的情况下,数据类型声明为:
- (BOOL)save:(NSError* __autoreleasing *)errorPointer;
which in English says "pointer to an __autoreleasing NSError object pointer".
用英文表示“指向 __autoreleasing NSError 对象指针的指针”。
回答by Glen Low
The definitive ARC specificationsays that
在明确的ARC规范说
For __autoreleasing objects, the new pointer is retained, autoreleased, and stored into the lvalue using primitive semantics.
对于 __autoreleasing 对象,新指针被保留、自动释放并使用原始语义存储到左值中。
So for example, the code
例如,代码
NSError* __autoreleasing error = someError;
actually gets converted to
实际上被转换为
NSError* error = [[someError retain] autorelease];
... which is why it works when you have a parameter NSError* __autoreleasing * errorPointer
, the called method will then assign the error to *errorPointer
and the above semantics will kick in.
...这就是为什么当您有参数时它会起作用NSError* __autoreleasing * errorPointer
,然后被调用的方法会将错误分配给*errorPointer
并且上述语义将启动。
You could use __autoreleasing
in a different context to force an ARC object into the autorelease pool, but that's not terribly useful since ARC only seems to use the autorelease pool at method return and already handles that automatically.
您可以__autoreleasing
在不同的上下文中使用强制 ARC 对象进入自动释放池,但这并不是非常有用,因为 ARC 似乎只在方法返回时使用自动释放池并且已经自动处理了。