我开始学习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参数传递时,这并不是我所期望看到的。
苹果开发者网站上说
所以问题是,有没有办法避免复制传递给函数的对象(我可以有一个相当大的数组或字典),或者Swift不允许我们做这样的事情?
发布于 2017-08-10 13:44:43
复制数组和字符串很便宜(几乎是免费的),只要您不修改它。Swift在stdlib中为这些集合实现了副本即写。这不是语言级别的特性;它实际上是为数组和字符串(以及其他一些类型)显式实现的。因此,您可以拥有多个大型数组的副本,它们都共享相同的备份存储。
inout
与“通过引用”不是一回事。从字面上说,这就是“外泄”。该值在函数开始时复制,然后复制回原来的位置。
Swift的方法通常用于通用,但Swift并没有像C++那样做出强大的性能承诺。(也就是说,这允许Swift在某些情况下比C++更快,因为Swift在数据结构的选择上没有受到限制。)作为一般规则,我发现很难对任意Swift代码的性能进行推理。最坏情况下的性能很容易推理(假设副本总是会发生),但是很难确定什么时候会避免复制。
发布于 2017-08-10 13:54:19
尽管inout
参数修改了用作函数输入参数的变量,但它们在其他语言中的工作方式与引用不同。Swift
中的行为称为复制复制或通过值结果调用。这意味着当您使用inout
参数时,在函数调用时,它的值被复制,并且在函数中,变量的本地副本将被修改。在函数返回时,它用修改后的复制值覆盖inout
参数原始内存位置的值。
您要在函数的中打印变量的地址,因此实际上是打印复制值的位置。在函数返回后尝试打印,您将看到正在使用修改后的值打印原始位置。
有关更多信息,请参见文档的输入输出参数部分。
https://stackoverflow.com/questions/45615408
复制相似问题