传递对象会增加保留计数

Passing an object around increases retain count

iOS,过渡到 ARC。我观察到关于 CF/NS 桥接的奇怪行为。在以下情况下:

CFStringRef cfs = ComesFromSomewhere();
NSString *ns = (__bridge NSString*)cfs;

最后字符串对象的保留计数为2。但是,在以下内容中:

NSString *ToNS(CFStringRef cfs)
{
    return (__bridge NSString*)cfs;
}

CFStringRef cfs = ComesFromSomewhere();
NSString *ns = ToNS(cfs);

最后保留计数为 3。请问这是怎么回事?谁拥有额外的参考资料?对象是否仅通过传递就被添加到自动释放池中?

对 "don't worry, ARC just works" 的先发制人的回应:我在这里将 Core Foundation 与 Cocoa 混合在一起,没有办法绕过它。这很容易泄漏。如果无法明确说明保留计数,我就瞎了。

编辑:它是调试版本的产物。在release build中,后一种情况下的retain count仍然是2.

留下大型自动释放对象的片段和没有留下大型自动释放对象的片段之间存在明显的区别;你不希望前者在循环体中没有池的大循环中。有助于了解它是零优化的产物,但仍然不酷。

CFStringRef cfs = ComesFromSomewhere();

// retainCount -> 1

NSString *ns = ToNS(cfs);

// ToNS(cfs)
//
// ToNS is not object creating method,
// thus the returned object was automatically autoreleased
// retainCount += 1

// NSString *ns
// 
// It's __strong variable, ns variable has an ownership of the object
// retainCount += 1

// retainCount -> 3

object creating method的定义是Objective-Cclass的名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法。参见 Basic Memory Management Rules - You own any object you create

In the release build, the retain count under the latter scenario is still 2.

如果符合条件,编译器也可以忽略向对象发送自动释放消息。

已编辑

您可以使用 C++ 参考来避免自动释放。

void ToNS(CFStringRef cfs, NSString __strong *& ns)
{
    ns = (__bridge NSString*)cfs;
}

NSString *nsstr;
ToNS(cfstr, nsstr);

// retainCount -> 2

已编辑

NS_RETURNS_RETAINED NSString *ToNS(CFStringRef cfs)
{
    return (__bridge NSString*)cfs;
}

NS_RETURNS_RETAINED 使框架将函数视为创建一个对象的对象(它确实是)。 Cocoa 有一个命名约定,允许您将方法指定为对象创建者,但该约定仅适用于 Objective C class 方法,不适用于 C 样式函数,不适用于 C++ class成员函数。