struct MyStruct {
private var myInt: Int = 1
// ... lots and lots of stored properties
mutating func increaseMyInt() {
myInt += 1
}
}
/* call to function _copies_ argument to function property 'myHugeStruct' (copy 1)
function property is mutated
function returns a copy of mutated property to caller (copy 2) */
func myFunc(var myHugeStruct: MyStruct) -> MyStruct {
myHugeStruct.increaseMyInt()
return myHugeStruct
}
/* call-by-reference, no value copy overhead due to inout opimization */
func myFuncWithLessCopyOverhead(inout myHugeStruct: MyStruct) {
myHugeStruct.increaseMyInt()
}
var a = MyStruct()
a = myFunc(a) // copy, copy: overhead
myFuncWithLessCopyOverhead(&a) // call by reference: no memory reallocation
同样,在上面的例子中---不考虑内存问题---inout可以作为一个很好的代码实践,告诉任何阅读我们代码的人我们正在改变函数调用者参数(通过函数调用中参数前面的&符号&隐式地显示)。 如果希望函数修改参数值,并且希望这些更改在函数调用结束后保持不变,请将该参数定义为in-out参数。 从Apple Language Guide: Functions - In-Out Parameters开始。 有关inout的详细信息以及它在内存中实际是如何处理的(名称copy-in-copy-out有点误导...)---除了上面的语言指南链接之外---请参见下面的SO线程:
struct MyStruct {
var myStructsIntProperty: Int = 1
mutating func myNotVeryThoughtThroughInoutFunction (inout myInt: Int) {
myStructsIntProperty += 1
/* What happens here? 'myInt' inout parameter is passed to this
function by argument 'myStructsIntProperty' from _this_ instance
of the MyStruct structure. Hence, we're trying to increase the
value of the inout argument. Since the swift docs describe inout
as a "call by reference" type as well as a "copy-in-copy-out"
method, this behaviour is somewhat undefined (at least avoidable).
After the function has been called: will the value of
myStructsIntProperty have been increased by 1 or 2? (answer: 1) */
myInt += 1
}
func myInoutFunction (inout myInt: Int) {
myInt += 1
}
}
var a = MyStruct()
print(a.myStructsIntProperty) // 1
a.myInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 2
a.myNotVeryThoughtThroughInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 3 or 4? prints 3.
8条答案
按热度按时间aij0ehis1#
inout
表示修改局部变量也会修改传入的参数,如果没有它,传入的参数还是原来的值,尝试在使用inout
时考虑引用类型,而不使用值类型。例如:
swap
函数是一个很好的用例,它将修改传入的参数。inout
关键字必须在冒号 * 之后 * 和类型之前。例如,Swift 3+现在需要func changeChar(char: inout Character)
。vom3gejh2#
来自Apple语言参考:说明-输入输出参数:
作为一种优化,当参数是存储在内存中物理地址的值时,在函数体内部和外部都使用相同的内存位置。它满足了复制入复制出模型的所有要求,同时消除了复制的开销。不要依赖于复制入复制出和引用调用之间的行为差异。
如果你有一个函数,它接受一个有点内存方面的大值类型作为参数(比如说,一个大的结构类型),并且返回相同的类型,最后函数返回总是用来替换调用者参数,那么
inout
是首选的关联函数参数。考虑下面的例子,这里的注解描述了为什么我们要使用
inout
而不是常规的类型返回类型函数:同样,在上面的例子中---不考虑内存问题---
inout
可以作为一个很好的代码实践,告诉任何阅读我们代码的人我们正在改变函数调用者参数(通过函数调用中参数前面的&符号&
隐式地显示)。如果希望函数修改参数值,并且希望这些更改在函数调用结束后保持不变,请将该参数定义为in-out参数。
从Apple Language Guide: Functions - In-Out Parameters开始。
有关
inout
的详细信息以及它在内存中实际是如何处理的(名称copy-in-copy-out
有点误导...)---除了上面的语言指南链接之外---请参见下面的SO线程:上面Lucas Huang给出的例子试图---在使用
inout
参数的函数作用域中---访问作为inout
参数传递的变量。这是不推荐的,并且在ref语言中被明确警告不要这样做:不要访问作为in-out参数传递得值,即使原始参数在当前作用域中可用.当函数返回时,您对原始参数所做得更改将被副本得值覆盖.不要依赖引用调用优化得实现来防止更改被覆盖.
现在,在这种情况下的访问是“唯一的”不可变的,例如
print(...)
,但是按照惯例,应该避免所有这样的访问。应一位评论者的要求,我将添加一个例子来阐明为什么我们不应该真正对 “作为in-out参数传递的值” 做任何事情。
因此,在本例中,inout的行为类似于copy-in-copy-out(而不是通过引用)。
不要依赖于复制入复制出和引用调用之间的行为差异。
omhiaaxx3#
默认情况下,函数参数是常量。试图在函数体中更改函数参数的值会导致编译时错误。这意味着您不能错误地更改参数的值。如果希望函数修改参数的值,并且希望这些更改在函数调用结束后保持不变,请将该参数定义为in-out参数。
im9ewurl4#
输入输出参数:修改传递和局部变量值。
sigwle7e5#
inout参数允许我们更改值类型参数的数据,并在函数调用完成后保持更改。
b91juud36#
如果你使用类,那么,正如你所说的,你可以修改类,因为参数是对类的引用。但是当你的参数是值类型时,这就不起作用了(https://docs.swift.org/swift-book/LanguageGuide/Functions.html- In-Out参数部分)
使用inout的一个很好的例子是这个(定义CGPoints的数学):
6pp0gazn7#
基本上,当你想玩变量的地址时,它是有用的,它在数据结构算法中非常有用
bq3bfh9z8#
当使用输入输出参数swift 4.0 Work时