Swift 初阶 —— inout 参数 & 数据独占问题

一、前言

我们都知道, 在 swift 里 inout 参数是用来修改实参的. 但其实 inout 参数的使用是要遵循"数据独占性"的, 要不然编译器会报错或警告.

inout 参数实际上只把对象的地址传了进来.

二、数据独占性

1、什么是数据独占

简单来说, "数据独占" 就是在单线程环境下, 当你往一块连续的内存写东西的同时, 不能读这块内存且不能同时往这块内存写其他东西.

2、为什么只有值类型才会有数据独占, 引用类型没有

这就涉及到 Swift 的设计哲学了. 因为一个引用类型的对象是一个指针而已, 且这个指针指向的实例是在堆上创建的, 所以这个堆上的实例是允许同时被多个指针指着的, 所以这个堆上的实例天生被设计出来就是为了共享的, 因此就引用类型没有数据独占这一说了.

但一个值类型的对象就是一块在栈上的连续内存, 不是指针. 所以值类型对象天生的设计就是不被共享的, 所以 Swift 才会在传 inout 参数时对值类型的对象实施数据独占.

3、访问重叠

3.1. 什么是访问重叠

访问重叠就是给多个 inout 参数传同一块连续内存. 这样做会导致 Swift 认为你在这个函数里同时对这块连续内存多次写入, 或边写边读, 于是 Swift 就认为你在破坏数据独占.

3.2. 访问重叠经典例子

3.2.1. 向多个 inout 参数传同一块连续内存

a. 同一个变量

b. 同一个数组(因为数组是内存连续的)

c. 同一个 struct 对象
图1 图 1 报错原因:

因为 state 传的是整块 appState 的内存, 而 max 传的是 appState 里的 limit 那块内存, 这两块内存是重叠了的, 所以 Swift 会怀疑你会对重叠的那部份内存边读边写, 于是就会报访问重叠 (overlapping accesses) 的错误.
图2 图 2 没报错原因:

这其实是 Swift6 的优化. appState 的 counter 和 appState 的 limit 这两块内存是不重叠的, 因此把这两块内存传到 value 和 max, 不会引起访问重叠的错误. 但这只是对 struct 的优化, 并不是对所有值类型对象的优化.

3.2.2. mutating 方法里使用逃逸闭包, 并在逃逸闭包里向 inout 参数写入

图 3 图 3 报错原因:

  1. inout 参数实际上只把对象的地址传了进来.
  2. mutating 方法实际会把 self 以 inout 的形式传进来, 因此 mutating 方法会对 self 要有数据独占性. 而如果如图 3 所示在逃逸闭包里修改 self, Swift 会认为你会在调用其他 mutating 方法时执行这个闭包, 那么对其他 mutating 方法而言就做不到 "数据独占" 了 (因为其他 mutating 函数里可能会出现同时向同一块内存写入的情况).
    图 4 图 4 为正确解决方案:

当我们把 self 声明在捕获列表里后, swift 实际上会把 self 拷贝出一个只读的副本, 然后再让闭包捕获这个不可变的副本. 所以闭包读到的 self 和 mutating 捕获到的 self 就不是同一块内存了, 就保证了 mutating 函数的 self 的数据独占.

三、总结

所以综上所述, swift 对 inout 参数的规定就是: inout 参数只能在当前函数的作用域内访问, 同时不能访问重叠. 除此之外, mutating 函数、setter、didSet & willSet 实际上都会把 self 以 inout 的方式传进来, 因此不能再这些函数里建一个逃逸闭包, 然后再在这个逃逸闭包里向 self 写值.

相关推荐
点心的游戏开发世界13 小时前
GDScript 入门笔记(十六):文件读写与数据持久化
开发语言·笔记·游戏引擎·godot
会飞的拖把13 小时前
Python序列详解:列表、元组、字符串的通用操作(超详细版)
开发语言·windows·python
reasonsummer13 小时前
【办公类-115-01】20260906育儿知识(家园小报)批量制作(2026年9月-2027年6月)
开发语言·数据库·c#
君顾113 小时前
智慧场馆解决方案小程序系统实战:从架构设计到上线指南
java·开发语言·智慧场馆
zhougl99613 小时前
Dockerfile实战教程
java·开发语言·spring boot
FfHUCisI13 小时前
Golang 网络轮询器 netpoll:把阻塞 IO 变成事件通知
开发语言·网络·golang
XiaoQiao66699913 小时前
C 语言常用头文件及里面核心函数
c语言·开发语言
statistican_ABin13 小时前
中国宠物经济发展分析报告——基于R语言的2018-2024年宠物市场多维度分析
开发语言·r语言·宠物
matlab代码14 小时前
基于matlab PCA人脸识别系统【源码63期】
开发语言·matlab
Terra.K14 小时前
后端开发阶段性总结
java·开发语言·后端