如果我在XCode 12操场(SWIFT5.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类型是免税的吗?
发布于 2020-10-26 22:04:24
这并不是因为Cocoa类型是豁免的,而是因为NSMutableDictionary是一个class (相对于struct),而且inout没有引用您可能想到的内容。
不幸的是,您链接到的文档(以及更多的in-depth documentation on inout parameters links to)没有说明“值”的真正含义:
输入输出参数具有传递给函数的值,该值由函数修改,并从函数中传回以替换原始值。
下面的声明暗示了这一点,但可能会更清楚:
您只能传递一个变量作为输入输出参数的参数。不能将常量或文字值作为参数传递,因为常量和文字不能被修改。
文档描述的“值”是作为inout传递的变量。对于值类型(structs),这是有意义的,因为每个包含这些类型值的变量都有效地持有该值的副本。
var a = MyGreatStruct(...)
var b = a
// a and b are not directly linked in any way将struct传递给函数通常会将值复制到一个新的局部变量中( normally = copy),而您可以想象inout允许您直接访问原始变量(没有新变量)。
没有描述的是,对于行为不同的类,其效果是相同的。
let a = MyGreatClass(...)
let b = a
// modifying `a` will modify `b` too since both point to the same instance将一个class传递给函数也会将变量复制到一个新的局部变量中,但是这个复制没有意义--这两个变量都持有相同的内容:内存中对对象本身的引用。从这个意义上说,复制没有什么特别之处,您可以从函数的内部修改对象,就像从外部修改对象一样。类的inout的行为方式与struct的相同:它通过引用传递原始变量。这与您想要在对象上执行的大多数操作没有关系(尽管它确实允许您将变量指向函数中的另一个对象):
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>https://stackoverflow.com/questions/64545417
复制相似问题