Inout 和 NSMutableDictionary
Inout and NSMutableDictionary
如果我 运行 XCode 12 playground (Swift 5.3) 中的以下代码,我从两个列表中得到相同的结果:
import Foundation
var dict = NSMutableDictionary()
dict["x"] = 42
func stuff(_ d: inout NSMutableDictionary) {
d["x"] = 75
}
stuff(&dict)
dump(dict) // x is 75
其他:
import Foundation
var dict = NSMutableDictionary()
dict["x"] = 42
func stuff(_ d: NSMutableDictionary) {
d["x"] = 75
}
stuff(dict)
dump(dict) // x is 75 still
根据此处的文档,第二个列表应该给我一个错误:
https://docs.swift.org/swift-book/LanguageGuide/Functions.html
但它仍然有效。
这是因为这些进出规则的实施仅限于 Swift 类型,而 Cocoa 类型是豁免的吗?
这不是因为 Cocoa 类型是豁免的,而是因为 NSMutableDictionary
是 class
(相对于 struct
),而 inout
不是指你可能在想什么。
不幸的是,您 link 的文档(以及更多 in-depth documentation on inout
parameters it links to)没有明确说明“价值”的真正含义:
An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value
下面的语句稍微暗示了一点,但可能更清楚:
You can only pass a variable as the argument for an in-out parameter. You cannot pass a constant or a literal value as the argument, because constants and literals cannot be modified.
文档描述的“值”是作为inout
传递的变量。对于值类型 (struct
s),这是有意义的,因为每个持有这些类型值的变量有效地持有该值的一个副本。
var a = MyGreatStruct(...)
var b = a
// a and b are not directly linked in any way
通常将 struct
传递给函数 将值复制 到新的局部变量中(新变量 = 复制),而您可以想象 inout
让您直接访问 原始 变量(没有新变量)。
没有描述的是效果 与 类 相同,它们的行为不同。
let a = MyGreatClass(...)
let b = a
// modifying `a` will modify `b` too since both point to the same instance
将 class
传递给函数也会 将变量复制 到一个新的局部变量中,但复制没有意义——两个变量持有相同的东西: 对内存中对象本身的引用。从这个意义上讲,复制并没有做任何特别的事情,您可以像从外部一样从函数内部修改对象。 类 的 inout
与 struct
s 的行为方式相同:它通过引用传递 原始变量 。这与您想要对对象执行的大多数操作无关(尽管它确实允许您从函数内部使变量指向 different 对象) :
var a = MyGreatClass("Foo")
// func foo(_ value: MyGreatClass) {
// value = MyGreatClass("Bar") // <- not allowed since `value` isn't mutable
// }
func foo(_ value: inout MyGreatClass) {
value = MyGreatClass("Bar")
}
print(ObjectIdentifier(a)) // <some pointer>
foo(&a)
print(ObjectIdentifier(a)) // <some other pointer>
如果我 运行 XCode 12 playground (Swift 5.3) 中的以下代码,我从两个列表中得到相同的结果:
import Foundation
var dict = NSMutableDictionary()
dict["x"] = 42
func stuff(_ d: inout NSMutableDictionary) {
d["x"] = 75
}
stuff(&dict)
dump(dict) // x is 75
其他:
import Foundation
var dict = NSMutableDictionary()
dict["x"] = 42
func stuff(_ d: NSMutableDictionary) {
d["x"] = 75
}
stuff(dict)
dump(dict) // x is 75 still
根据此处的文档,第二个列表应该给我一个错误: https://docs.swift.org/swift-book/LanguageGuide/Functions.html
但它仍然有效。
这是因为这些进出规则的实施仅限于 Swift 类型,而 Cocoa 类型是豁免的吗?
这不是因为 Cocoa 类型是豁免的,而是因为 NSMutableDictionary
是 class
(相对于 struct
),而 inout
不是指你可能在想什么。
不幸的是,您 link 的文档(以及更多 in-depth documentation on inout
parameters it links to)没有明确说明“价值”的真正含义:
An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value
下面的语句稍微暗示了一点,但可能更清楚:
You can only pass a variable as the argument for an in-out parameter. You cannot pass a constant or a literal value as the argument, because constants and literals cannot be modified.
文档描述的“值”是作为inout
传递的变量。对于值类型 (struct
s),这是有意义的,因为每个持有这些类型值的变量有效地持有该值的一个副本。
var a = MyGreatStruct(...)
var b = a
// a and b are not directly linked in any way
通常将 struct
传递给函数 将值复制 到新的局部变量中(新变量 = 复制),而您可以想象 inout
让您直接访问 原始 变量(没有新变量)。
没有描述的是效果 与 类 相同,它们的行为不同。
let a = MyGreatClass(...)
let b = a
// modifying `a` will modify `b` too since both point to the same instance
将 class
传递给函数也会 将变量复制 到一个新的局部变量中,但复制没有意义——两个变量持有相同的东西: 对内存中对象本身的引用。从这个意义上讲,复制并没有做任何特别的事情,您可以像从外部一样从函数内部修改对象。 类 的 inout
与 struct
s 的行为方式相同:它通过引用传递 原始变量 。这与您想要对对象执行的大多数操作无关(尽管它确实允许您从函数内部使变量指向 different 对象) :
var a = MyGreatClass("Foo")
// func foo(_ value: MyGreatClass) {
// value = MyGreatClass("Bar") // <- not allowed since `value` isn't mutable
// }
func foo(_ value: inout MyGreatClass) {
value = MyGreatClass("Bar")
}
print(ObjectIdentifier(a)) // <some pointer>
foo(&a)
print(ObjectIdentifier(a)) // <some other pointer>