swift的inout的用法
在 Swift 中,
inout 关键字用于定义输入输出参数,允许函数修改传入参数的原始值(而非副本),实现 “传引用” 的效果(本质是 “传值 + 回写” 的语法糖)。以下是 inout 的核心用法、规则及示例:一、基本用法
1. 函数参数声明
在函数参数类型前添加
inout,表示该参数可被修改并反映到原始变量。swift
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
var x = 5, y = 10
swapTwoInts(&x, &y) // 调用时需加 & 符号
print(x, y) // 输出:10 5
2. 调用规则
- 传入的参数必须是变量(不能是常量或字面量);
- 调用时需在变量前加
&,显式标记 “允许修改”。
二、进阶场景
1. 修改结构体 / 枚举实例
inout 可用于修改结构体或枚举的属性(甚至整个实例):swift
struct Point {
var x: Int, y: Int
}
func moveUp(_ point: inout Point, by distance: Int) {
point.y += distance
}
var p = Point(x: 0, y: 0)
moveUp(&p, by: 5)
print(p) // 输出:Point(x: 0, y: 5)
2. 结合类型别名 / 泛型
swift
typealias IntPair = (a: Int, b: Int)
func modifyPair(_ pair: inout IntPair) {
pair.a *= 2
pair.b += 3
}
var pair = (a: 2, b: 4)
modifyPair(&pair)
print(pair) // 输出:(4, 7)
// 泛型示例
func reset<T>(_ value: inout T, to defaultValue: T) {
value = defaultValue
}
var str = "Hello"
reset(&str, to: "World")
print(str) // 输出:World
3. 嵌套函数 / 闭包中的 inout
闭包若需捕获
inout 参数,需显式标记 inout(Swift 5.3+):swift
func outerFunc(_ num: inout Int) {
let closure: (Int) -> Void = { increment in
num += increment // 直接修改外部 inout 参数
}
closure(10)
}
var num = 5
outerFunc(&num)
print(num) // 输出:15
三、注意事项
-
不可用于常量 / 字面量传入的参数必须是
var变量,不能是let常量或字面量(如5、"abc")。 -
与
let参数的区别普通参数默认是let(不可修改),inout参数本质是 “可写的变量”。 -
值类型 vs 引用类型
- 对于值类型(结构体、枚举、基本类型):
inout会修改原始值; - 对于引用类型(类):即使不用
inout,也能修改实例属性(inout仅用于修改引用本身,如替换整个实例)。
swiftclass Person { var name: String = "" } // 修改属性(无需 inout) func changeName(_ p: Person) { p.name = "Alice" } // 替换实例(需要 inout) func replacePerson(_ p: inout Person) { p = Person() p.name = "Bob" } var person = Person() changeName(person) print(person.name) // Alice replacePerson(&person) print(person.name) // Bob - 对于值类型(结构体、枚举、基本类型):
-
不能与
let/var/@escaping同时使用inout参数不能标记为let/var,也不能与@escaping同时修饰(避免逃逸闭包长期持有导致原始值失效)。
四、典型应用场景
- 交换两个变量的值(如
swap函数); - 批量修改结构体 / 枚举的属性;
- 函数需要 “返回多个修改后的值”(替代元组返回);
- 底层优化(减少值类型的拷贝开销)。
通过
inout,Swift 在保持值类型安全性的同时,提供了灵活的参数修改能力,是处理 “需要函数修改外部变量” 场景的核心工具。

浙公网安备 33010602011771号