美文网首页
Swift中值类型、引用类型:Struct 与Class区别与应

Swift中值类型、引用类型:Struct 与Class区别与应

作者: nero_i | 来源:发表于2021-01-07 09:22 被阅读0次

    Swift 中Class和Struct异同

    Swift 中类和结构体有很多共同点。共同处在于:

    • 定义属性用于存储值
    • 定义方法用于提供功能
    • 定义下标操作使得可以通过下标语法来访问实例所包含的值
    • 定义构造器用于生成初始化值
    • 通过扩展以增加默认实现的功能
    • 实现协议以提供某种标准功能

    与结构体相比,类还有如下的附加功能:

    • 继承允许一个类继承另一个类的特征
    • 类型转换允许在运行时检查和解释一个类实例的类型
    • 析构器允许一个类实例释放任何其所被分配的资源
    • 引用计数允许对一个类的多次引用

    Tip: 类的对象是引用类型,而结构体是值类型。所以类的赋值是传递引用,结构体则是Copy传值,不是使用引用计数。
    类为支持的额外功能会增加其复杂性。一般,更倾向使用选择结构和枚举,因为他们更容易理解,而类,则当再在合适和必要的时候使用。实际上,这意味着大多数的自定义数据类型定义为结构和枚举就可以了。


    值类型、引用类型 最基本的定义:

    值类型每个实例都拥有其数据的一份副本。当被赋值给一个变量或常量,或传递给一个函数时候,它会建立一份新的副本。

    引用类型所有实例共享一个数据副本。当被赋值给一个变量或常量,或传递给一个函数时候,一个引用类型一旦被初始化,会返回一个指向已存在实例的引用。

    比较项 struct class
    类型 值类型 引用类型
    属性初始化 可用默认构造直接初始化 需要自己创建构造方法
    变量赋值 深拷贝 浅拷贝,增加原对象引用
    方法中修改属性 需要添加mutating 不需要
    继承关系 不能继承 可以继承
    内存 栈上,自动内存管理 堆上,手动内存管理
    速度 高效 相比效率低
    线程安全 自动线程安全的 大多是非线程安全的
    与oc混编 不支持,oc无法调struct 支持混编
    序列化 不支持,可用字节转NSData 支持序列化

    Class优势 Struct

    • 混合开发中,OC无法调用swift的struct,因为oc调用swift代码,对象必须继承nsobject
    • struct不能相互继承,
    • struct不能被序列化成NSdata对象,所以不能存入NSUserDefaults,所以需要数据序列化,储存最好用class实现

    struct的优点

    • 安全性:Struct是值类型传递,没有引用计数
    • 内存:由于他没有引用计数,不会因为循环引动导致内存泄露
    • 速度:Struct 值类型通常是以栈分配,不是堆,所以Struct比class快的多
    • 拷贝:当你拷贝一个对象时不需要知道是深拷贝,浅拷贝
    • 线程安全:无论从那个线程访问Struct,都简单

    总结:
    各有优缺点,如果模型较小,无需继承和存储到NSUserDefaults,或无需oc使用时,可以用Struct。
    struct可以保证代码更加安全可靠,以及struct+protocol更加切合swift面向协议编程的初衷

    二、struct并不是swift中唯一的值类型,class也不是唯一的引用类型。下面是一些例子:

    值类型 引用类型
    Int Function
    Double Closures
    String NSString
    Array NSArray
    Dictionary NSDictionary
    Set NSSet
    Struct Class
    Enum NS 继承NSObject相关数据类型
    Tuple

    备注:Swift把一个引用类型看成一个类,这和Objective-C中很像。Objective-C中一切继承于NSObject都被按照引用类型存储

    三、我们什么时候选择值类型而不用引用类型?

    以下时候使用值类型:

    • 想要用==比较实例数据。一个双等号(==)用于比较值。

    • 你想复制来建立独立数据。

    • 数据要在多线程的代码中使用,那么你就不用担心数据会被其他线程改变。

    以下时候使用引用类型(比如一个类):

    • 想要用===比较实例一致性。===会检查两个对象是否完全一致,包括存储数据的内存地址。

    • 你想要创建用于共享,可改变的数据。

    引用类型和值类型在内存中怎么存储?

    • 值类型-在栈内存中存储
    • 引用类型-在托管堆内存中存储

    栈与堆的不同!

    像前面说的,引用类型实例存在堆中,值类型实例比如结构存在于一个称为栈的内存区域中。如果值类型实例是一个类的一部分,值会和类一起存在堆中。

    栈被用于静态存储分配,栈用于动态存储分配,它们都存在计算机的RAM中。

    栈被CPU紧密管理并优化,当一个函数创建一个变量,栈会存储这个变量,并在函数退出时候被毁掉。被分配到栈的变量直接存储在内存上,访问这段内存非常快。当一个函数或者方法调用另一个函数,另一个函数再依次调用其他函数等等,直到最后一个函数返回它的值之前,其他所有函数都会保持暂停执行。

    栈总是按照LIFO顺序保留,最新保留的区块总是会下一个释放。这使得跟踪记录栈非常简单,释放一个栈上的区块不过是调整一个指针。因为栈非常组织有序,所以它快捷高效。

    系统使用堆存储被其他对象引用的数据,堆是一大片内存,系统可以从中请求并动态分配内存区块。堆并不会像栈一样自动毁掉它的对象,需要外部工作来处理这些。在苹果设备中ARC就做这个工作。引用数量会被ARC追踪,当它变为0时对象会被释放。因此整个过程(分配,追踪引用,释放)会比栈要慢。所以值类型要快于引用类型。

    相关文章

      网友评论

          本文标题:Swift中值类型、引用类型:Struct 与Class区别与应

          本文链接:https://www.haomeiwen.com/subject/irhooktx.html