惰性初始化听起来很好用。为什么不总是默认使用惰性初始化?

Lazy Initialization sounds and works great. Why not always default to using lazy initialization?

看来惰性初始化很棒。我理解这个概念并测试了我的代码,我没有看到任何滞后。那么问题来了,为什么不总是使用惰性初始化呢?这有什么缺点?我没有意识到什么?

考虑 lazy var 的这个例子:

struct S {
    lazy var lazyVar: Int = { /* compute some value */ 0 }()
}

幕后真正发生的事情是这样的:

struct S {
    var _lazyVar: Int? = nil

    var lazyVar: Int {
        mutating get {
            if let existingValue = _lazyVar {
                return existingValue
            }
            else {
                let newlyComputedValue = /* compute some value */ 0
                _lazyVar = newlyComputedValue
                return newlyComputedValue
            }
        }
    }
}

如您所见,lazyVar 的每次访问都需要一个分支,以检查是否已经有一个值,或者是否有必要第一次计算一个值。这增加了开销,很容易超过通过简单(快速)推导延迟评估值的好处。

lazy 的最大缺点之一是 lazy 变量不能是常量。这个缺点最终会消除很多你必须将某些变量声明为 let 的情况。

在可读性方面,当其他开发人员阅读您的代码并看到 lazy 实现时,作为开发人员,我会立即知道这个变量是 运行 密集型的,或者这个变量在计算之前需要来自另一个来源的一些值。