【问题标题】:What is the difference in Swift between 'unowned(safe)' and 'unowned(unsafe)'?'unowned(safe)' 和 'unowned(unsafe)' 在 Swift 中的区别是什么?
【发布时间】:2014-12-20 15:30:20
【问题描述】:

Apple 的Swift Programming Language Guide 除了weakunowned 之外,还提到了捕获说明符 unowned(safe)unowned(unsafe)

我(想我)理解weakunowned 之间的区别;但是unowned(safe)unowned(unsafe) 有什么区别?指南没有说。


请:不要依赖于简单地陈述一个 Objective-C 等价物。

【问题讨论】:

    标签: memory-management swift automatic-ref-counting


    【解决方案1】:

    据我了解,虽然我无法从 Apple 找到明确的来源,但 unowned 可以分为两种风格,safeunsafe

    一个裸露的unownedunowned(safe):它是一个特殊包装的引用,当引用一个解除分配的实例时会抛出一个异常。

    特例是unowned(unsafe):它是Objective C 的@property (assign)__unsafe_unretained 的Swift 等价物。它不应该在 Swift 程序中使用,因为它的目的是连接到用 Objective C 编写的代码。

    因此,在查看 Cocoa 类的导入包装器时,您会看到 unowned(unsafe),但除非必须,否则不要使用它,并且您会知道何时需要。


    更新

    __unsafe_unretained 是一个简单的指针。它不会知道被指向的实例何时被释放,因此当它被取消引用时,底层内存可能是垃圾。

    如果您在使用已释放的__unsafe_unretained 变量时存在缺陷,您将看到不稳定的行为。有时该内存位置足够好,因此代码可以运行,有时它会被部分覆盖,因此您会遇到非常奇怪的崩溃,有时该内存位置将包含一个新对象,因此您会遇到无法识别的选择器异常。

    Transitioning to ARC Release Notes

    __unsafe_unretained 指定一个引用,该引用不会使被引用的对象保持活动状态,并且在没有对该对象的强引用时不设置为 nil。如果它引用的对象被释放,则指针悬空。

    【讨论】:

    • 但是那些 Objective-C 等价物是什么意思?
    • 因此,总而言之,与 strong 引用不同,weak 和所有 unowneds 不会对引用计数做出贡献。因此,一旦所有strong 引用都消失了,引用的实例将被释放(当只保留weakunowned 对它的引用时); weak 引用将设置为 nil(因此它们具有可选类型),而 unowned 不会。但是,unowned(safe) 对已释放实例的引用在访问时会引发可预测的异常,而 unowned(unsafe) 引用将像一个简单的旧指针一样运行,并且行为不可预测。对吗?
    • @raxacoricofallapatorius,不,这是不对的。 unownedunowned(safe) 确实会产生引用计数成本——这是安全成本,为什么还要让 unowned(unsafe) 可用?——而且它目前比常规的强引用计数成本更糟糕,因为 ARC 没有针对它进行优化。两者都不抛出异常;它们在被滥用时会陷入陷阱,从而永久停止程序。
    【解决方案2】:

    这是来自Apple Developer Forums的引用:

    unowned vs unowned(safe) vs unowned(unsafe)

    unowned(safe) 是一个非拥有引用,它在访问时断言 对象还活着。这有点像一个弱可选参考 每次访问时都会用x! 隐式解包。 unowned(unsafe) 就像 ARC 中的 __unsafe_unretained — 它是非拥有的 参考,但没有运行时检查对象是否仍然存在 在访问时,因此悬空引用将进入垃圾内存。 unowned 当前始终是 unowned(safe) 的同义词,但 意图是它将在-Ofast 中优化为unowned(unsafe) 在禁用运行时检查时构建。

    【讨论】:

    • 我刚刚使用 unowned 调试了一个崩溃,运行时检查被禁用,编译优化,其中 __deallocating_deinit 在存在对已删除对象的无主引用时断言。 (虽然我的代码在对象消失后从未引用过它。)所以 unowned(unsafe) 和 unowned 在禁用安全检查的情况下编译之间仍然存在差异。关于此的详细线程:twitter.com/RonAvitzur/status/1463576340519473159
    【解决方案3】:

    一个简单的定义。这将消除混乱。

    -- 无主属性:如果你在它引用的实例被释放后尝试访问一个无主引用,你的程序将会崩溃。

    -- unowned(Unsafe) 属性:如果你在它引用的实例被释放后尝试访问一个不安全的无主引用,你的程序将尝试访问该实例曾经所在的内存位置,这是一个不安全的手术。 (不保证这会执行还是崩溃)

    【讨论】:

      【解决方案4】:

      变量在已使用属性解除分配时被访问:

      无主

      • 程序知道它无效,并立即崩溃。
      • 行为已定义。

      无主(不安全)

      • 程序什么都不知道。
      • 它可能会立即崩溃。
      • 它可能会访问未知的内存地址并处于奇怪的状态,直到它在意外的位置死亡。
      • 行为未定义。生活变得更加艰难。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-10
        相关资源
        最近更新 更多