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

三、注意事项

  1. 不可用于常量 / 字面量 传入的参数必须是 var 变量,不能是 let 常量或字面量(如 5"abc")。

  2. let 参数的区别 普通参数默认是 let(不可修改),inout 参数本质是 "可写的变量"。

  3. 值类型 vs 引用类型

    • 对于值类型(结构体、枚举、基本类型):inout 会修改原始值;
    • 对于引用类型(类):即使不用 inout,也能修改实例属性(inout 仅用于修改引用本身,如替换整个实例)。

    swift

    复制代码
    class 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
  4. 不能与 let/var/@escaping 同时使用 inout 参数不能标记为 let/var,也不能与 @escaping 同时修饰(避免逃逸闭包长期持有导致原始值失效)。

四、典型应用场景

  • 交换两个变量的值(如 swap 函数);
  • 批量修改结构体 / 枚举的属性;
  • 函数需要 "返回多个修改后的值"(替代元组返回);
  • 底层优化(减少值类型的拷贝开销)。

通过 inout,Swift 在保持值类型安全性的同时,提供了灵活的参数修改能力,是处理 "需要函数修改外部变量" 场景的核心工具。

相关推荐
caimouse1 小时前
ReactOS 窗口系统分析(23):键盘 — keyboard.c + kbdlayout.c
c语言·开发语言·计算机外设
Emily156853598701 小时前
Emerson 1C31129G03 Analog Input Module
java·开发语言·前端·plc·emerson·1c31129g03·input module
就叫_这个吧6 小时前
Java递归方法实现面包屑导航
java·开发语言
fīɡЙtīиɡ ℡6 小时前
AI 应用系统设计
java·开发语言·人工智能
今天AI了吗8 小时前
Python 基础语法(一):常量、变量、输入输出与运算符
开发语言·数据库·人工智能·python·sql·深度学习·机器学习
TELL5218 小时前
selenium webdriver 第二次初始化的异常
开发语言·python
动词ing9 小时前
【C语言】自定义函数+指针入门
c语言·开发语言·算法
重生之后端学习9 小时前
283. 移动零[简单]✅
开发语言·数据结构·算法·leetcode·职场和发展
动词ing10 小时前
【C语言】结构体+文件基础
c语言·开发语言·数据结构
caimouse10 小时前
ReactOS 窗口系统分析(7):分层窗口与绘制辅助 — layered.c + draw.c
c语言·开发语言