在Swift

时间:2017-08-10 13:39:30

标签: swift swift3 memory-address

我开始学习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不允许我们做这些事情?

2 个答案:

答案 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部分。