【问题标题】:Implicit ownership qualifier for parameters/return type is always __strong?参数/返回类型的隐式所有权限定符始终是 __strong?
【发布时间】:2014-01-22 22:43:33
【问题描述】:

因为在具有自动引用计数的项目中,NSString * aString; 隐含地表示NSString * __strong aString;参数和返回类型是否也计算在内?

- (NSString *)doubleString:(NSString *)aString {
    return [NSString stringWithFormat:@"%@%@", aString, aString];
}

相同的编译代码
- (NSString * __strong)doubleString:(NSString * __strong)aString {
    return [NSString stringWithFormat:@"%@%@", aString, aString];
}

在所有类似的方法中?

【问题讨论】:

    标签: objective-c parameters automatic-ref-counting return-type ownership


    【解决方案1】:

    简短回答: 是的。两种变体都产生相同的编译代码,可以验证 通过 Xcode 菜单中的“产品 -> 执行操作... -> 组装 ...”。

    更长的答案:(以下参考文献和引文来自Clang/ARC 文档。)

    您关于返回值的问题。根据 "4 Ownership qualification", __strong__weak 之类的限定符适用于 内存中的位置,其中指针 存储到一个对象,并且它们在从加载或存储到时指定语义 左值 (4.2 Semantics)。

    方法的返回值不是内存中的这样一个位置(它不是一个左值), 因此所有权资格的概念在这里不适用。

    方法声明为返回(NSString * __weak)(NSString * __strong)没有区别,编译后的代码没有区别。

    一个稍微不同的问题是调用者是否拥有 返回对象(它有一个 +1 保留计数)与否。默认情况下,这取决于方法名称,如"3.2.2 Retained return values" 中所述 和"3.2.3 Unretained return values"

    您关于参数的问题。 将参数声明为 (NSString * __strong)(NSString *) 相同。这已经可以看到 来自 Xcode 自动补全(未显示“__strong”限定符),但是 也来自生成的汇编代码。

    这并不意味着在调用方法时参数会保留。 默认情况下,它们不是,如中所述 "3.2 Retainable object pointers as operands and arguments".

    如果一个参数被声明为__weak,它似乎(来自汇编代码)在方法中创建了一个临时弱引用,即

    - (NSString *) doubleString:(NSString * __weak)aString {
        return [NSString stringWithFormat:@"%@%@", aString, aString];
    }
    

    本质上是一样的

    - (NSString *) doubleString:(NSString *)aString {
        NSString *__weak wString = aString;
        return [NSString stringWithFormat:@"%@%@", wString, wString];
    }
    

    但我无法找到明确的参考。

    【讨论】:

    • 所以在参数和返回类型中写 __strong/__weak 是完全错误的,并且会像使用 __weak 参数一样创建错误的代码,还是会像返回类型一样被忽略? (所有权以其他方式声明)。
    • @ViktorLexington:如果我理解正确的话,__strong/__weak 对于返回类型没有任何意义。在我看来它是错误的,但编译器似乎只是忽略了它。 - 将 __weak 添加到 parameter 并没有错,但我不明白 为什么 应该这样做。
    • 一种特殊情况:仅在参数列表中,SomeObjectType** 隐含为SomeObjectType * __autoreleasing *(即指向自动释放指针的指针)。这样做是为了使 NSError** 与预先存在的 NSError 约定一起工作。
    猜你喜欢
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 2021-10-13
    • 2011-06-23
    相关资源
    最近更新 更多