一个母亲和两个儿子的故事:价值类型与参考类型Swift中的参考类型
斯威夫特是一个母亲和有两个儿子 -
- 价值类型♀️
- 参考类型♂️
但是他们的特征是什么?♂️
它们的行为相同还是相反?♂️
Swift是Apple为iOS,MacOS,WatchOS,TVOS,Linux和Z/OS开发的多范式编程语言。
就像其他面向对象的编程语言一样,Swift也具有可以定义方法,属性,初始化器并可以符合协议,支持继承和多态性的构建块。
但是,等等等等…
Swift也具有结构,它可以定义方法,属性,初始化器,并且只能符合协议,但仅一个继承。
什么?现在我很困惑!!!
现在,让我们加重您的困惑:结构不仅是Swift中的价值类型。元组和枚举也是价值类型。类也不是唯一用作参考类型的类。功能和关闭也是参考类型。但是,作为宽慰的象征,我们至少知道这些类型使用的主要重点和专业化。
因此,到目前为止,我们对结构和类的使用只有一个很大的困惑。
所以,让我们去清除困惑。
存储位置
可用的三种类型的存储类型:
- 登记
- 堆栈☄️
- 堆
寿命较短的对象存储在寄存器或堆栈中,以及寿命更长的物体存储在堆内。
值类型将其内容存储在堆栈中分配的内存中,因此我们可以说价值类型在Swift中分配了。
但是对价值类型有一个普遍的误解,您听到了吗?♂️
误解是,大多数人认为价值类型总是存储在堆栈中。
❌❌等待一分钟 - 永远不是这种情况。❌❌
当值类型是临时变量或局部变量时,可以将其存储在堆栈中。但是,如果参考类型中包含值类型怎么办?
在这种情况下,它可以存储在堆内存中。
哇...太酷了!!!
因此,价值类型可以根据其寿命(无论是短暂的还是长寿)存储在寄存器,堆栈或堆中。如果它是局部变量,它可以生活在堆栈内,如果它是类的一部分,则它也可以生活在堆内存中。
另一方面,参考类型将其内容存储在分配在堆内存中的内存中,并且变量仅具有对存储实际数据的该内存位置的引用。
它如何用于参考类型?
因此,对于参考类型,当可能有几个变量保存对同一内存位置的变量时,这是一个很普遍的情况。
当将值类型实例分配给变量或传递给函数时,将将实例复制并分配给该变量。但是,使用参考类型,只有参考被复制,而新变量则具有相同的引用对同一内存位置。
在可变性方面的差异
可以有两个变量的状态:
- ♀Mutable
- 目标不变了梦
如果将值类型实例分配给不可变的变量,则该实例也变得不可变。结果,我们无法对该实例进行任何更改。
如果将值类型实例分配给可变变量,则只能使实例可变。♂️
但是参考类型的情况完全不同。变量及其分配的实例完全不同。如果我们声明一个不可变的变量保存对类的引用,则意味着它持有的参考将永远不会改变。我们无法更改参考,它将始终指向相同的参考。
结构类型
就其属性或元素而言,比较了结构类型的值。我们可以说,当且仅当所有相应属性等于时,一个值类型等于另一种类型。
嗯……太多的强烈词……你是什么意思?
假设我们有一个人具有类似属性的价值类型名和姓。
结构人{var firstName:字符串var lastname:字符串}var person1 = person(firstName:“ foo”,lastname:“ bar”)var person2 = person(firstName:“ foo”,lastname:“ bar”)
这两个人1和人2实例具有相同的价值名(“ foo”)和lastname(“ bar”)。因此,根据我们的理解,我们可以说这两个实例彼此平等,因为它们的属性(名和姓)拥有相同的值。
但这不仅限于这一点:将来,任何两个人的实例都持有相同的价值观名和姓将彼此平等。
因此,根据我们的理解,我们可以说:
价值类型没有身份,因此不能参考它们。价值类型是无面的。
什么?你怎么能这么说呢?
var myage:int = 21
VAR搭配:int = 21
两个都我的年龄和品牌是具有值21的整数类型变量。
我们可以区分另一个吗?
不,因为他们拥有相同的价值。
具有值21的整数变量不能与另一个具有值21的整数变量不同。
没有身份给出价值类型的另一个优点:如果您实际思考,那么您可以想象,如果您没有身份,那么任何具有相同特征的人都可以替换或替换您。
我们也可以认为我们也是人类。如果我没有身份,那么任何具有相同特征的人都可以取代我。对我们来说,我们有一个身份对我们来说是一件好事,否则这将是我们生存的巨大风险。
但是对于价值类型,它们没有身份,这对他们来说是一个优势。
使用价值类型有什么好处?
没有种族条件和僵局:
对于多线程环境中的值类型,一个线程在另一个线程使用时不可能突变实例的状态。因此,我们可以说不会有种族条件或僵局。
⚔️没有保留周期:⚔️
当有两个参考类型实例相互持有强烈的引用并防止对方从内存中划分时,它称为保留周期。由于价值类型不能用作参考,因此我们可以说价值类型不会保留周期。
自动参考计数:
对于参考类型,Swift使用自动参考计数来跟踪所有实时或活动对象,并仅在不再有强大引用的情况下才能处理该实例。如果我们有一点思考,那么我们可以说这是一个沉重的操作,因为快速运行时需要始终跟踪对象。但是,由于在堆栈中分配了价值类型,因此它不需要弧。因此,它更便宜,更快。
但是等等...它如何管理数组,字典和字符串的内存?
由于我们不知道在编译时数组,字典和字符串的实际大小是什么,因此在编译时没有分配它们的范围。尽管它们是内部的价值类型,但不能分配在堆栈中。他们需要分配在堆内存中,为了管理这一点,Swift提出了复制写。
但是这是什么?
当我们说一个实例是另一个实例的副本时,这确实意味着它们是相同的,它们包含相同的值。但是在Swift中,对于上述类型(数组,字典,字符串等),仅在实例突变时才在堆上进行实际副本。这称为价值类型的性能优化技术。
结论
没有硬规则可以定义何时使用值类型以及何时使用参考类型。价值类型比参考类型具有一些独特的优势,反之亦然。他们俩都是独一无二的。这实际上取决于您的要求以及您要实现的目标。您应该知道代码的语义,因为您只了解代码,因此可以选择。你有充分的自由。
因此,与其对价值类型与参考类型进行战斗,不如聪明地使用它们。
干杯!!!谢谢你的阅读!
✅✅✅你可以找到我推特.✅✅✅