我开始学习c ++,现在我想知道我是否也可以在Swift中做一些事情。
当我们将变量作为参数传递给Swift中的函数时,我从未真正考虑过会发生什么。
让我们使用string
类型的变量作为示例。
在c ++中,我可以通过复制一个函数或者通过引用/指针将参数传递给函数。
void foo(string s)
或void foo (string& s)
;
在第一种情况下,将创建原始变量的副本, foo 将收到副本。在第二种情况下,我基本上在内存中传递变量的地址而不创建副本。
现在在Swift中,我知道我可以将函数的参数声明为 inout ,这意味着我可以修改原始对象。
1)func foo(s:String)
...
2)func testPassingByReference(s: inout String)
...
我对String进行了扩展,以打印对象的地址:
extension String {
func address() -> String {
return String(format: "%p", self);
}
}
结果并非我期望看到的结果。
var str = "Hello world"
print(str.address())
0x7fd6c9e04ef0
func testPassingByValue(s: String) {
print("he address of s is: \(s.address())")
}
func testPassingByReference(s: inout String) {
print("he address of s is: \(s.address())")
}
testPassingByValue(s: str)
0x7fd6c9e05270
testPassingByReference(s: &str)
0x7fd6c9e7caf0
我理解为什么当我们按值传递参数时地址不同,但是当我们将参数作为inout参数传递时,它不是我期望看到的。
Apple开发者网站说
In Swift, Array, String, and Dictionary are all value types.
所以问题是,有没有办法避免复制我们传递给函数的对象(我可以有一个非常大的数组或字典)或者Swift不允许我们做这些事情?
答案 0 :(得分:3)
只要不修改数组和字符串就很便宜(几乎免费)。 Swift在stdlib中为这些集合实现了copy-on-write。这不是语言级别的功能;它实际上是为数组和字符串(以及其他一些类型)显式实现的。因此,您可以拥有许多共享相同后备存储的大型阵列的副本。
inout
与“通过引用”不同。它实际上是“进出”。该值将在函数开头复制,然后复制回到最后的原始位置。
Swift的方法往往适用于常见用途,但Swift没有像C ++那样做出强大的性能承诺。 (也就是说,这允许Swift在某些情况下比C ++更快,因为Swift的数据结构选择并不受限制。)作为一般规则,我发现很难推断出可能的性能。任意Swift代码。很容易推断最坏情况下的性能(只是假设副本总是发生),但很难确定何时会避免副本。
答案 1 :(得分:3)
尽管inout
参数修改了用作函数输入参数的变量,但它们并不像其他语言中的引用那样完全正常工作。 Swift
中的行为称为 copy-in copy-out或按值结果调用。这意味着当您使用inout
参数时,在函数调用时,会复制其值,并在函数内部修改变量的本地副本。在函数返回时,它会使用修改后的副本值覆盖inout
参数原始内存位置的值。
您正在打印函数内部的地址,因此您实际上正在打印复制值的位置。返回函数后尝试打印,您将看到正在使用修改后的值打印原始位置。
有关详细信息,请参阅文档的In-Out parameters部分。