Swift通过价值或通过参考传递

问题描述 投票:85回答:7

我是Swift的新手,我只是读取类通过引用传递,数组/字符串等被复制。

通过引用传递的方式与Objective-C或Java中的方式相同,其中您实际传递“a”引用或是否通过引用正确传递?

swift pass-by-reference pass-by-value pass-by-pointer
7个回答
152
投票

Types of Things in Swift

规则是:

  • 类实例是引用类型(即您对类实例的引用实际上是指针)
  • 函数是引用类型
  • 其他一切都是价值类型; “其他一切”只是意味着结构和枚举实例的实例,因为这就是Swift的全部内容。例如,数组和字符串是结构实例。你可以通过使用inout并获取地址来传递对这些事物之一的引用(作为函数参数),正如newacct指出的那样。但类型本身就是一种价值类型。

What Reference Types Mean For You

引用类型对象在实践中是特殊的,因为:

  • 仅仅赋值或传递给函数可以产生对同一对象的多个引用
  • 即使对它的引用是常量(let,无论是显式的还是隐含的),对象本身都是可变的。
  • 对象的变异会影响该对象,如所有对它的引用所见。

那些可能是危险的,所以要留意。另一方面,传递引用类型显然是有效的,因为只复制并传递指针,这是微不足道的。

What Value Types Mean For You

显然,传递值类型是“更安全”,而let意味着它所说的:你不能通过let引用来改变结构实例或枚举实例。另一方面,安全是通过单独复制价值来实现的,不是吗?这是否会使传递值类型的价格变得昂贵?

嗯,是的,不。它没有你想象的那么糟糕。正如Nate Cook所说,传递值类型并不一定意味着复制,因为let(明示或暗示)保证不变性,因此不需要复制任何东西。甚至传入var引用并不意味着事情将被复制,只有在必要时它们才会被复制(因为存在突变)。文档特别建议你不要让你的短裤扭曲。


41
投票

当参数不是inout时,它总是按值传递。

如果参数是inout,它总是通过引用传递。但是,这有点复杂,因为您需要在传递给&参数时在参数上显式使用inout运算符,因此它可能不适合直接传递变量的传递的传递定义。


35
投票

默认情况下,Swift中的所有内容都通过“复制”传递,因此当您传递值类型时,您将获得该值的副本,并且当您传递引用类型时,您将获得引用的副本,其中包含所有含义。 (也就是说,引用的副本仍然指向与原始引用相同的实例。)

我在上面的“副本”周围使用了恐慌引用,因为Swift做了很多优化;只要有可能,它就不会复制,直到出现突变或突变的可能性。由于默认情况下参数是不可变的,这意味着大多数情况下实际上没有复制。


7
投票

这是一个通过引用传递的小代码示例。避免这样做,除非你有充分的理由。

func ComputeSomeValues(_ value1: inout String, _ value2: inout Int){
    value1 = "my great computation 1";
    value2 = 123456;
}

像这样称呼它

var val1: String = "";
var val2: Int = -1;
ComputeSomeValues(&val1, &val2);

6
投票

Apple Swift Developer博客有一个名为Value and Reference Types的帖子,它提供了关于这个主题的清晰而详细的讨论。

报价:

Swift中的类型分为两类:第一类是“值类型”,其中每个实例都保留其数据的唯一副本,通常定义为struct,enum或tuple。第二种是“引用类型”,其中实例共享数据的单个副本,并且类型通常被定义为类。

Swift博客文章继续解释与示例的差异,并建议何时使用一个而不是另一个。


1
投票

类通过引用传递,其他类默认按值传递。您可以使用inout关键字通过引用传递。


1
投票

当您使用inout和中缀运算符(例如+ =)时,可以忽略&地址符号。我想编译器假定通过引用传递?

extension Dictionary {
    static func += (left: inout Dictionary, right: Dictionary) {
        for (key, value) in right {
            left[key] = value
        }
    }
}

origDictionary + = newDictionaryToAdd

很好的是,这个字典'添加'只会写一个原始参考,非常适合锁定!

© www.soinside.com 2019 - 2024. All rights reserved.