You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中inout与引用类型疑问:类实例为何仍需加&?

为什么Swift中引用类型作为inout参数时仍需加&?

好问题!这确实是Swift里inout参数和引用类型容易搞混的地方,咱们把这个事儿掰明白:

首先先回顾下值类型的情况,比如你提到的swapTwoInts函数:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

Int是值类型,默认函数参数是传值拷贝——也就是函数拿到的是原始值的副本,修改副本不会影响原始变量。而inout的作用就是让函数能直接操作原始变量的内存,&就是告诉Swift:“把这个变量的地址传进去,允许函数修改它本身”。

那到了引用类型(比如自定义类)这里,很多人会觉得“既然类是引用传递,直接传实例不就能改了?为啥还要加&?”——这里的关键是要分清修改对象的属性和修改变量的引用是两回事:

  • 当你把类实例作为普通参数传递时,函数拿到的是引用的拷贝(也就是指向堆上对象的指针副本)。这时候你可以修改对象的属性(因为指针指向同一个对象),但你没法让原始变量指向一个新的对象——因为你修改的只是指针的副本,原始变量里的指针没变。
  • 而inout参数的作用,就是允许函数修改原始变量本身的存储内容——对于引用类型来说,变量存储的是指向对象的指针,所以inout能让函数把这个指针换成新的(也就是让变量指向另一个对象)。这时候就必须用&来传递,告诉Swift我们要修改的是变量本身的存储,而不是仅仅操作它指向的对象。

举个实际的例子就清楚了:

class Person {
    var name: String
    init(name: String) {
        self.name = name
    }
}

// 普通参数:只能修改对象属性,没法改变变量的引用
func updatePersonName(_ person: Person) {
    person.name = "Alice"
    // 下面这行代码毫无意义,因为person是引用的拷贝,修改的是副本,原始变量不会变
    // person = Person(name: "Bob")
}

// inout参数:可以修改变量的引用,让它指向新对象
func replacePerson(_ person: inout Person) {
    person = Person(name: "Bob") // 这会直接修改原始变量的引用
}

var myPerson = Person(name: "Charlie")
updatePersonName(myPerson)
print(myPerson.name) // 输出 "Alice",因为修改的是同一个对象

replacePerson(&myPerson)
print(myPerson.name) // 输出 "Bob",因为myPerson现在指向了新的Person实例

总结一下:inout的核心是允许函数修改原始变量的存储内容,不管这个内容是值类型的具体值,还是引用类型的指针。所以当你需要让函数改变引用类型变量的指向时,就必须用&来传递inout参数;如果只是修改对象的属性,那普通参数就足够了,不需要inout和&。

内容的提问来源于stack exchange,提问作者Wike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:42:51