我编写了一个用于序列化模型数据的简单库,后来意识到当我只是阅读时我正在写入数据。我能够将问题减少到以下游乐场片段:
class Foo {
init() { name = "test" }
var name:String { didSet { print("setting name: \(self.name)") }}
}
func map(inout foo:String) {
print("writing value: \(foo)")
}
var foo:Foo = Foo()
map(&foo.name)
结果是(对我而言)意外:
写作值:测试
设置名称:test
我已经重新阅读了inout
参数的部分,但没有明确提到复制语义。我的预感是编译器期望覆盖该值,并且如果没有其他代码这样做,则使用初始值。
这似乎是预期的,还是编译器错误?以我的拙见,这是不直观的行为。我不期待任务,除非它源于我的代码 - 它没有。
要陈述希望显而易见的内容,上面的代码片段不需要inout参数,但我一直在使用通用接口进行读写。
答案 0 :(得分:3)
我是代表Joe Groff发布的,这是一个Swift编译器开发人员on Twitter(参见回复)。他很好地回答了我提到这个问题的推文。
他说:
Inout具有值结果语义。 didSet在inout的末尾接收修改后的值。如果差异是不可观察的(模数无效别名),它只会优化传递引用。 Swift书也应该用这个信息更新。
答案 1 :(得分:2)
您可以通过将inout关键字放在其参数定义的开头来编写输入输出参数。输入输出参数具有传递给函数的值,由函数修改,并从函数传递回替换原始值。
输入输出参数不是“按引用调用”,而是“call-by-copy-restore”