Swift中值类型与引用类型的深入剖析

立即解锁
发布时间: 2025-09-12 01:52:38 阅读量: 10 订阅数: 35 AIGC
PDF

Swift编程实战精要

### Swift 中值类型与引用类型的深入剖析 #### 1. 值类型与引用类型的混合使用 在编程中,我们常常会思考能否将值类型置于引用类型内,或者将引用类型置于值类型内。答案是两者皆可。例如,在 `Company` 结构体中添加 `Employee` 类型的属性,就是将引用类型置于值类型内。不过,在值类型中使用引用类型时需格外谨慎,而在引用类型中使用值类型通常不会有特别的问题。 假设 `Acme Co.` 重组为 `Widget Co.`,在审核员工记录时,`Anika` 发现自己的员工编号实际上是 15 而非 16。以下代码展示了这一过程: ```swift mel.id = 86 mel.id // 86 acme.boss.id // 16 let widgetCo = acme anika.id = 15 widgetCo.boss.id // 15 ``` 当记录 `acme.boss.id` 的值时,结果为 16。接着,将 `acme` 的副本赋值给新常量 `widgetCo`。由于 `Company` 是值类型,本应期望 `widgetCo` 是 `acme` 的副本。随后,将 `anika` 的 ID 更新为 15。最后,检查 `widgetCo` 的老板 ID 时会发现其变为 15,这反映了 `anika` ID 的更改。这是因为 `boss` 属性是 `Employee` 类型,而 `Employee` 是类,属于引用类型。即便 `Company` 是值类型,其引用类型的属性依然只是引用。 这一示例表明,在值类型中放置引用类型会带来复杂性。通常,值类型的实例在赋值给新变量或常量,或者作为参数传递给函数时会被复制。但包含引用类型属性的值类型,会将对同一实例的引用传递给新变量或常量。通过任何一个常量或变量的属性对该实例所做的更改,都会在所有相关对象中体现。为避免混淆,一般应避免在值类型中使用引用类型属性。若确实需要在结构体中使用引用类型属性,最好使用不可变实例。 #### 2. 复制操作 复制的概念贯穿本章几乎所有主题。开发者常想了解复制实例时得到的是浅复制还是深复制。在 Swift 中,语言层面不支持深复制,因此复制操作均为浅复制。 以下示例有助于理解这些概念。假设 `Widget Co.` 招聘了一名新员工,创建一个新的 `Employee` 实例并将所有实例放入数组: ```swift let juampa = Employee() let employees = [anika, mel, juampa] // [{id 15}, {id 86}, {id 0}] ``` 创建新员工 `juampa` 并将其与 `anika` 和 `mel` 加入新数组。在为公司派对邀请名单添加人员时,`Anika` 发现 `Juampa` 的 ID 录入有误。于是复制 `employees` 数组,更新 `juampa` 的 ID 并比较两个数组: ```swift let juampa = Employee() let employees = [anika, mel, juampa] // [{id 15}, {id 86}, {id 0}] let partyGoers = employees // [{id 15}, {id 86}, {id 0}] employees.last?.id = 4 employees // [{id 15}, {id 86}, {id 4}] partyGoers // [{id 15}, {id 86}, {id 4}] ``` 数组是结构体,属于值类型,本应期望 `partyGoers` 是 `employees` 的独立副本。但更改 `juampa` 的 ID 属性后,两个数组内容相同。这是因为 `employees` 数组包含 `Employee` 类型(引用类型)的实例,`partyGoers` 和 `employees` 数组引用的是相同的 `Employee` 实例,类似于 `acme` 和 `widgetCo` 共享对 `Employee` 的引用。 这种复制方式称为浅复制。浅复制不会遍历引用,值类型的浅复制复制值,引用类型的浅复制复制引用。而深复制会复制引用指向的实例,即 `partyGoers` 数组的元素不会引用与 `employees` 数组相同的 `Employee` 实例,而是创建一个新数组,其中的引用指向各自的 `Employee` 实例。Swift 未提供执行深复制的方法,若需要此功能,需自行实现。 #### 3. 相等性与同一性 理解值类型和引用类型的区别后,接下来探讨相等性和同一性。相等性指两个实例的可观察特征值相同,例如两个 `String` 类型的实例具有相同的文本。以下代码展示了相等性检查: ```swift let x = 1 let y = 1 x == y // true ``` 创建两个常量 `x` 和 `y`,它们均为 `Int` 类型且值相同,使用 `==` 进行相等性检查结果为 `true`。所有 Swift 的基本数据类型(如 `String`、`Int`、`Float`、`Double`、`Array`、`Set` 和 `Dictionary`)都可进行相等性检查。 同一性则指两个引用是否指向内存中的同一实例。由于 `Employee` 是引用类型,可使用同一性运算符 `===` 检查两个 `Employee` 实例的同一性: ```swift acme.boss === anika // true ``` 此同一性检查成功,并非因为 `Acme` 的老板与 `anika` 属性相同,而是因为 `Acme` 的老板就是 `anika`。再看以下代码: ```swift let joe = Employee() let sam = Employee() joe === sam // false ``` 此同一性检查失败,尽管 `joe` 和 `sam` 的员工 ID 均为 0,但它们并非指向同一实例。 若尝试对 `x` 和 `y` 进行同一性检查,使用 `x === y` 会导致编译器报错。因为 `===` 运算符用于检查引用类型变量所引用实例的内存地址,值类型变量不存储引用,所以同一性检查无意义。若尝试检查 `joe` 和 `sam` 的相等性,使用 `joe == sam` 也会引发编译器错误,因为编译器不知道如何在 `Employee` 类上调用 `==` 函数。若要对自定义类进行相等性检查,需实现 `==` 函数,这涉及遵循 `Equatable` 协议。 需要注意的是,两个常量或变量可能相等(即具有相同的值)但不同一(即可能指向给定类型的不同实例),但反之不成立:若两个变量或常量指向内存中的同一实例,则它们也相等。 #### 4. 如何选择 结构体和类都适合定义许多自定义类型。在 Swift 之前,在 macOS 和 iOS 开发中,结构体与类差异显著,两者的使用场景清晰。但在 Swift 中,结构体功能增强,行为与类更为相似,这使得选择使用哪种类型变得复杂。不过,结构体和类仍存在重要差异,可作为选择的参考: - 若希望类型通过引用传递,应使用类。这样能确保该类型在赋值或作为函数参数传递时被引用而非复制。 - 若类型需要支持继承,则使用类,因为结构体不支持继承,不能被子类化。 - 否则,通常可选择结构体。 结构体常用于建模形状(如矩形有宽度和高度)、范围(如比赛有开始和结束)以及坐标系中的点(如二维空间中的点有 x 和 y 值),也适用于定义数据结构,Swift 标准库中的 `String`、`Array` 和 `Dictionary` 类型均定义为结构体。 在某些情况下,可能更倾向于使用类而非结构体,但这些情况相对较少,主要是需要引用语义或继承。例如,若想利用引用传递的优势,但又不希望类被子类化,可使用 `final` 类,标记为 `final` 的类不能被子类化,同时其实例可具有所需的引用语义。一般建议先使用结构体,除非确定需要引用类型的优势。值类型更易于理解,因为无需担心在副本上更改值时实例会发生什么。 #### 5. 写时复制(Copy on Write) Swift 的复制行为可能会引发性能问题,例如每次将数组传递给函数或赋值
corwn 最低0.47元/天 解锁专栏
买1年送3月
继续阅读 点击查看下一篇
profit 400次 会员资源下载次数
profit 300万+ 优质博客文章
profit 1000万+ 优质下载资源
profit 1000万+ 优质文库回答
复制全文

相关推荐

陆鲁

资深技术专家
超过10年工作经验的资深技术专家,曾在多家知名大型互联网公司担任重要职位。任职期间,参与并主导了多个重要的移动应用项目。
最低0.47元/天 解锁专栏
买1年送3月
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
千万级 优质文库回答免费看
立即解锁

专栏目录

最新推荐

从仿真到硬件:基于FPGA的PMF-FFT捕获实现全路径解析(Matlab到RTL落地)

![从仿真到硬件:基于FPGA的PMF-FFT捕获实现全路径解析(Matlab到RTL落地)](https://www.logic-fruit.com/wp-content/uploads/2023/11/ARINC-429-Standards-1024x536.jpg) # 摘要 本文围绕FPGA与卫星信号捕获技术展开研究,重点分析PMF-FFT捕获算法的理论基础、建模仿真及其在FPGA上的系统实现。文章从扩频通信与伪码同步原理出发,推导PMF-FFT算法的数学模型,并基于Matlab平台完成算法建模与性能验证。随后,研究了算法从浮点到定点的转换过程,完成了模块划分与FPGA资源映射设

LIN协议栈数据结构设计与内存优化策略(例程工程实践)

![lin协议栈例程工程文件](https://www.zgsm-china.com/wp-content/uploads/2023/11/Street-light-control.jpg) # 摘要 本文围绕LIN协议栈的数据结构与内存管理机制展开系统性研究,重点分析其核心设计目标、通信模型与数据交互机制,并深入探讨数据结构设计中的可扩展性、数据对齐及状态机实现等关键技术。针对内存管理,本文比较了静态与动态内存分配策略,提出了基于内存池、结构体压缩和位域优化的多种内存优化方法,并讨论了嵌入式环境下内存泄漏与碎片化的防控机制。通过在不同MCU架构上的工程实践,验证了优化策略在内存占用与性

智能控制方法在波浪能电能管理中的应用:模糊控制、神经网络等实战解析

# 摘要 本文围绕波浪能电能管理系统中的智能控制方法展开研究,系统阐述了模糊控制与神经网络控制的理论基础及其融合策略。通过建立波浪能系统的动态模型,设计并验证了基于模糊控制的能量管理策略,同时探讨了神经网络在电能预测中的应用实现。进一步提出了智能控制系统的硬件平台构建、控制算法嵌入式实现及系统优化方法,明确了关键性能指标与多目标优化路径。研究旨在提升波浪能系统的能量转换效率与运行稳定性,为未来智能控制在可再生能源领域的应用提供技术支撑。 # 关键字 波浪能系统;模糊控制;神经网络;能量管理;动态建模;多目标优化 参考资源链接:[直驱式波浪能发电仿真及其电能管理技术研究](http

数据安全完整方案:Metabase备份与恢复操作的5个最佳实践

![数据安全完整方案:Metabase备份与恢复操作的5个最佳实践](https://d2908q01vomqb2.cloudfront.net/887309d048beef83ad3eabf2a79a64a389ab1c9f/2021/07/21/DBBLOG-1488-image001.png) # 摘要 Metabase作为企业数据分析的重要工具,其数据安全性和备份恢复机制至关重要。本文系统探讨了Metabase在数据安全方面的核心问题,深入分析其架构组成与备份恢复机制,详细介绍了全量备份、增量备份、冷备份与热备份等策略的适用场景。文章结合实践,阐述了备份计划制定、数据库操作、应用

多壁碳纳米管建模验证全流程:LAMMPS结构构建实战指南

![多壁碳纳米管建模验证全流程:LAMMPS结构构建实战指南](https://static.wixstatic.com/media/49f946_e60f68ea432b45c5b39545e4d36705a7~mv2.png/v1/fill/w_980,h_551,al_c,q_90,usm_0.66_1.00_0.01,enc_auto/49f946_e60f68ea432b45c5b39545e4d36705a7~mv2.png) # 摘要 本文围绕多壁碳纳米管的建模方法与分子动力学模拟技术展开,系统介绍了基于LAMMPS平台的建模流程与力学性能分析手段。首先阐述了碳纳米管的几何

毫米波雷达设计新思路:PO方法在车载雷达中的5大应用场景解析

![毫米波雷达设计新思路:PO方法在车载雷达中的5大应用场景解析](https://www.vikylin.com/wp-content/uploads/2023/10/Discover-Practical-Uses-of-Motion-Detection-in-Surveillance-Cameras-Systems.jpg) # 摘要 本文围绕物理光学(PO)方法在车载毫米波雷达设计中的应用展开系统研究,首先介绍毫米波雷达技术的基本原理及其在智能驾驶中的应用场景,随后深入阐述物理光学方法的理论基础、建模流程及其在复杂目标与多路径环境下的适用性。文章重点分析了PO方法在行人识别、障碍物

深入MATLAB求解器内核:3种ODE算法在船舶动力学中的性能对比

![船舶仿真,船舶仿真工艺,matlab](https://i0.wp.com/sdcverifier.com/wp-content/uploads/2018/03/plate_stresses.png?w=1170&ssl=1) # 摘要 本文围绕MATLAB常微分方程(ODE)求解器在船舶动力学建模中的应用展开系统研究。首先介绍了ODE的基本分类及其数学形式,分析了MATLAB求解器的核心机制,包括步长控制、误差估计与求解器类型选择。随后详细推导并实现了三种典型数值算法:四阶龙格-库塔法(RK4)、阿达姆斯-巴什福斯法(Adams-Bashforth)和后向微分公式法(BDF),并结

火电机组调频与电力系统稳定协同建模:Matlab多系统联合仿真全解析

![火电机组调频与电力系统稳定协同建模:Matlab多系统联合仿真全解析](https://img-blog.csdnimg.cn/2091f692e9af48518ac9c139708304cf.jpeg) # 摘要 本文围绕火电机组调频与电力系统稳定协同建模展开系统研究,首先分析火电机组调频的基本原理与动态建模方法,重点探讨一次调频与二次调频机制及关键参数影响,并基于Matlab/Simulink构建调频仿真模型。随后,深入研究电力系统稳定性的核心理论与建模技术,涵盖静态与暂态稳定分析及同步发电机建模。进一步提出火电机组与电网系统的多域协同建模方法与联合仿真框架,解决数值稳定性与模型

移动设备适配DSDIFF Decoder:资源优化与性能调优关键策略

![移动设备适配DSDIFF Decoder:资源优化与性能调优关键策略](https://img-blog.csdnimg.cn/direct/8979f13d53e947c0a16ea9c44f25dc95.png) # 摘要 本文围绕DSDIFF音频格式在移动设备上的解码与适配问题展开研究,系统解析了DSD音频原理及DSDIFF文件结构,深入探讨了解码流程、转换机制与主流解码器架构,并分析了移动平台在音频处理中面临的CPU、内存与操作系统限制。针对资源瓶颈,本文提出多线程解码、内存复用、NEON加速等优化策略,并结合动态频率调整与后台调度实现功耗控制。通过性能基准测试与实际调优案例

Intel I219-V MAC修改失败?这10个常见问题你必须知道

![Intel I219-V MAC修改失败?这10个常见问题你必须知道](https://www.ubackup.com/screenshot/es/others/windows-11/crear-soporte-de-instalacion.png) # 摘要 Intel I219-V网卡作为主流有线网络接口,其MAC地址的可配置性在特定应用场景中具有重要意义。本文系统阐述了Intel I219-V网卡的技术架构与MAC地址修改的实现机制,涵盖从操作系统层面到BIOS/UEFI底层的多种修改方法。针对实际操作中常见的修改失败问题,本文深入分析了驱动兼容性、固件限制及主板策略等关键因素