首页 文章

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

提问于
浏览
112

我正在努力完成这个难题 .

__strong 是所有Objective-C可保留对象指针的默认值,如NSObject,NSString等 . 这是一个强大的参考 . ARC在范围的末尾与 -release 进行 balancer .

__unsafe_unretained 等于旧的方式 . 它用于弱指针而不保留可保留对象 .

__weak__unsafe_unretained 类似,不同之处在于它是一个自动归零的弱引用,这意味着一旦引用的对象被释放,指针就会被设置为nil . 这消除了悬空指针和EXC_BAD_ACCESS错误的危险 .

但究竟是什么 __autoreleasing 适合?我'm having a hard time finding practical examples on when I need to use this qualifier. I believe it'仅适用于期望指针指针的函数和方法,例如:

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

要么

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

在ARC下必须以这种方式声明:

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

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

此外,可能还有其他情况我必须依赖 __autoreleasing .

3 回答

  • 66

    definitive ARC specification

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

    例如,代码

    NSError* __autoreleasing error = someError;
    

    实际上转换为

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

    ...这就是为什么当你有一个参数 NSError* __autoreleasing * errorPointer 时它会工作的原因,被调用的方法然后将错误分配给 *errorPointer ,上面的语义将会启动 .

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

  • 33

    你是对的 . 正如官方文件所述:

    __autoreleasing表示通过引用(id *)传递的参数,并在返回时自动释放 .

    所有这一切都在_413961中得到了很好的解释 .

    在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 来避免这种情况 .

  • 14

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

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

    前言,使用限定符声明对象指针的正确语法是:

    NSError * __qualifier someError;
    

    编译器会原谅这个:

    __qualifier NSError *someError;
    

    但这不正确 . 请参阅the Apple ARC transition guide(阅读以"You should decorate variables correctly..."开头的部分) .

    解决手头的问题:双指针不能有ARC内存管理限定符,因为指向内存地址的指针是指向基本类型的指针,而不是指向对象的指针 . 但是,当您声明双指针时,ARC确实想知道第二个指针的内存管理规则是什么 . 这就是为什么双指针变量被指定为:

    SomeClass * __qualifier *someVariable;
    

    因此,在方法参数是双NSError指针的情况下,数据类型声明为:

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

    英文中的“指向__autoreleasing NSError对象指针的指针” .

相关问题