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

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时对象会被释放。因此整个过程(分配,追踪引用,释放)会比栈要慢。所以值类型要快于引用类型。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容