提问人:gran_profaci 提问时间:12/9/2014 更新时间:3/23/2022 访问量:107746
是 Swift 按值传递还是按引用传递
Is Swift Pass By Value or Pass By Reference
问:
我真的是 Swift 的新手,我刚刚读到类是通过引用传递的,数组/字符串等是复制的。
通过引用传递的方式是否与在 Objective-C 或 Java 中实际传递“a”引用的方式相同,或者它是否正确通过引用传递?
答:
默认情况下,Swift 中的所有内容都是通过“copy”传递的,所以当你传递一个值类型时,你会得到一个值的副本,当你传递一个引用类型时,你会得到一个引用的副本,以及所有这意味着的。(也就是说,引用的副本仍指向与原始引用相同的实例。
我在上面的“副本”周围使用恐吓引号,因为 Swift 做了很多优化;在可能的情况下,它不会复制,直到出现突变或突变的可能性。由于参数在默认情况下是不可变的,这意味着大多数时候实际上不会发生复制。
评论
当参数不 时,它始终是按值传递的。inout
如果参数为 ,则始终是按引用传递的。但是,由于在传递给参数时需要在参数上显式使用运算符,因此它可能不符合传统的按引用传递定义,即直接传递变量,因此这有点复杂。inout
&
inout
评论
inout
)
Swift 中的事物类型
规则是:
类实例是引用类型(即对类实例的引用实际上是一个指针)
函数是引用类型
其他一切都是值类型;“其他一切”只是指结构体的实例和枚举的实例,因为这就是 Swift 的全部内容。例如,数组和字符串是结构体实例。正如 newacct 所指出的那样,您可以通过使用和获取地址来传递对其中之一的引用(作为函数参数)。但该类型本身就是一个值类型。
inout
参考类型对您意味着什么
引用类型对象在实践中是特殊的,因为:
仅仅赋值或传递给函数就可以产生对同一对象的多个引用
对象本身是可变的,即使对它的引用是一个常量(显式或隐含)。
let
对象的突变会影响该对象,如对它的所有引用所看到的那样。
这些可能是危险的,所以要留意。另一方面,传递引用类型显然是有效的,因为只复制和传递指针,这是微不足道的。
价值类型对您意味着什么
显然,传递值类型是“更安全”的,这意味着它所说的:你不能通过引用来改变结构实例或枚举实例。另一方面,这种安全性是通过单独复制值来实现的,不是吗?这难道不会使传递值类型的成本可能很高吗?let
let
嗯,是也不是。它并不像你想象的那么糟糕。正如 Nate Cook 所说,传递值类型并不一定意味着复制,因为(显式或隐式)保证了不可变性,因此无需复制任何内容。即使传递到引用中也不意味着事物将被复制,只是在必要时它们可以被复制(因为存在突变)。文档特别建议您不要弄乱内裤。let
var
评论
inout
class Dog {var name = "fido "}
func f(_ dog: Dog) {dog.name = "rover"}
Apple Swift 开发者博客有一篇名为“值和引用类型”的文章,对这个主题进行了清晰而详细的讨论。
引用:
Swift 中的类型分为两类:第一类是“值类型”, 其中每个实例都保留其数据的唯一副本,通常定义 作为结构、枚举或元组。第二种是“引用类型”,其中 实例共享数据的单个副本,类型通常为 定义为类。
Swift 的博客文章继续通过示例解释这些差异,并建议何时使用其中一个而不是另一个。
评论
默认情况下,类按引用传递,其他类按值传递。
您可以使用关键字通过引用进行传递。inout
评论
inout
下面是一个用于引用传递的小代码示例。 避免这样做,除非你有充分的理由这样做。
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);
评论
inout
当您将 inout 与中缀运算符(如 +=)一起使用时,可以忽略 &address 符号。我猜编译器假设通过引用传递?
extension Dictionary {
static func += (left: inout Dictionary, right: Dictionary) {
for (key, value) in right {
left[key] = value
}
}
}
origDictionary += newDictionaryToAdd
而且,这本词典“添加”也只写到原始引用,非常适合锁定!
类和结构
结构和类之间最重要的区别之一是,在代码中传递结构时,结构总是被复制的,但类是通过引用传递的。
闭 包
如果将闭包分配给类实例的属性,并且该闭包通过引用该实例或其成员来捕获该实例,则将在闭包和实例之间创建一个强引用循环。Swift 使用捕获列表来打破这些强大的引用周期
ARC(自动参考计数)
引用计数仅适用于类的实例。结构和枚举是值类型,而不是引用类型,并且不通过引用进行存储和传递。
Swift ,以及 for 的引用值和 copy 的值assign
pass
return
reference type
Value Type
如果与你比较,你可以找到匹配项:Java
- Java 引用类型(所有对象)
- Java primitive type(int, bool...) - Swift 使用
struct
struct 是一种值类型,因此它始终作为值传递。让创建结构体
//STEP 1 CREATE PROPERTIES
struct Person{
var raw : String
var name: String
var age: Int
var profession: String
// STEP 2 CREATE FUNCTION
func personInformation(){
print("\(raw)")
print("name : \(name)")
print("age : \(age)")
print("profession : \(profession)")
}
}
//allow equal values
B = A then call the function
A.personInformation()
B.personInformation()
print(B.name)
当我们更改“B”的值时,它的结果相同,因为 A 的值被复制了,因此 B 中发生了更改,例如 B.name = “Zainab” B的名字发生了变化。它是按价值传递
按引用传递 类总是使用通过引用传递,其中只复制占用内存的地址,当我们像结构一样改变B的值时,A和B都因为引用被复制而改变。
评论