在 Swift 中通过引用传递变量

Ale*_*xei 5 memory-address swift swift3

我开始学习 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

结果并不是我所期望看到的。

var str = "Hello world"
print(str.address()) 
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

0x7fd6c9e05270

testPassingByReference(s: &str)
Run Code Online (Sandbox Code Playgroud)

0x7fd6c9e7caf0

我理解为什么当我们按值传递参数时地址不同,但当我们将参数作为 inout 参数传递时,这不是我期望看到的。

苹果开发者网站说

在 Swift 中,Array、String 和 Dictionary 都是值类型。

所以问题是,有没有办法避免复制我们传递给函数的对象(我可以有一个相当大的数组或字典)或者 Swift 不允许我们做这样的事情?

Rob*_*ier 5

只要不修改数组和字符串,复制数组和字符串的成本就很便宜(几乎免费)。Swift 在 stdlib 中为这些集合实现了写时复制。这不是语言级别的功能;而是语言级别的功能。它实际上是为数组和字符串(以及其他一些类型)显式实现的。因此,您可以拥有大型阵列的多个副本,它们都共享相同的后备存储。

inout与“通过引用”不同。从字面上看,它是“进出”。该值在函数开始时被复制,然后在函数结束时复制回原始位置。

Swift 的方法对于常见用途来说往往具有高性能,但 Swift 并没有像 C++ 那样做出强有力的性能承诺。(也就是说,这使得 Swift 在某些情况下比 C++ 更快,因为 Swift 在数据结构的选择上不受限制。)作为一般规则,我发现很难推断出可能的性能任意 Swift 代码。很容易推断出最坏情况的性能(假设总是发生副本),但很难确定何时会避免副本。