讨论Struct与Class之前,我们先来看一个概念:Value Type(值类型),Reference Type(引用类型):
1. 值类型的变量直接包含他们的数据,对于值类型都有他们自己的数据副本,因此对一个变量操作不可能影响另一个变量;
2. 引用类型的变量存储对他们的数据引用,因此后者称为对象,因此对一个变量操作可能影响另一个变量所引用的对象
两者的本质区别在于:深拷贝就是内容拷贝,浅拷贝就是指针拷贝
从而引出了深拷贝和浅拷贝
https://www.cnblogs.com/beckwang0912/p/7212075.html
1.浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针。
浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象。
2.深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。
深拷贝就是拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。
深拷贝就是内容拷贝,浅拷贝就是指针拷贝。本质区别在于:
是否开启新的内存地址 深拷贝开启新的内存地址 浅拷贝不
是否影响内存地址的引用计数 浅拷贝影响引用计数 深拷贝不
回到上面说的 值类型和引用类型上
class 为类, struct 为结构体, 类是引用类型, 结构体为值类型, 结构体不可以继承。
https://www.cnblogs.com/beckwang0912/p/8508299.html
先举两个开发中常用的例子:
分别创建一个结构体和一个类对象 里面都包含有属性变量 从而可以观察出他们的区别
1.初始化方式并不一样
主要的差別就是 class 在初始化时不能直接把 property(属性) 放在 默认的constructor(初始化方法) 的参数里,而是需要自己创建一个带参数的constructor
2.变量赋值方式不同(深浅copy)
struct 赋值“=”的时候,会copy一份完整相同的內容给另一個变量 --> 【开辟了新的内存地址】
( 此中引出了写实复制概念 copy on write
写时复制, 指的是 swift 中的值类型, 并不会在一开始赋值的时候就去复制, 只有在需要修改的时候, 才去复制
每次将struct赋值给其它变量或者传递给函数时并不是都会发生复制 在Swift中的Array、Dictionary、String这些类型中,尽管它们都是值类型,但在Swift的具体实现中做了优化,可以避免不必要的复制。在Swift中采用的优化方式叫做写时复制技术,简单的说就是,只有当一个结构体发生了写入行为时才会有复制行为。具体的做法就是,在结构体内部用一个引用类型来存储实际的数据,在不进行写入操作的普通传递过程中,都是将内部的reference的应用计数+1,在进行写入操作时,对内部的reference做一次copy操作用来存储新的数据,防止和之前的reference产生意外的数据共享。
在Swift3中这个函数变成了这样:isKnownUniquelyReferenced,他能检查一个类的实例是不是唯一的引用,如果是,我们就不需要对结构体实例进行复制,如果不是,说明对象被不同的结构体共享,这时对它进行更改就需要进行复制。
)
class 赋值“=”的时候,不会copy一份完整的内容给另一個变量,只是增加了原变量内存地址的引用而已 --> 【没有开辟了新的内存地址】
3。immutable 变量
Swift 语言的特色之一就是可变动内容和不可变内容用 var 和 let 來甄别,如果初始为let的变量再去修改会发生编译错误。
struct也遵循这一特性
class不存在这样的问题
4.mutating(可变) function(函数)
struct 和 class 的差別是 struct 的 function 要去改变 property 的值的时候要加上 mutating,而 class 不用。
5.继承
struct不能继承,class可以继承。
6.struct比class更“轻量级”
struct分配在栈中,class分配在堆中。
(此处引出了堆和栈问题)
我们在开发中 class和struct都可以作为数据模型 class不需要多说了 当我们把 Struct 作为数据模型的时候 需要有几点注意的事项
优点:
1、安全性:
因为 Struct 是用值类型传递的,它们没有引用计数。
2、内存:
由于他们没有引用数,他们不会因为循环引用导致内存泄漏。
3、速度:
值类型通常来说是以栈的形式分配的,而不是用堆。因此他们比 Class 要快很多! (http://stackoverflow.com/a/24243626/596821)
4、拷贝:
Objective-C 里拷贝一个对象,你必须选用正确的拷贝类型(深拷贝、浅拷贝),而值类型的拷贝则非常轻松!
5、线程安全
值类型是自动线程安全的。无论你从哪个线程去访问你的 Struct ,都非常简单。
缺点:
1、Objective-C
当你的项目的代码是 Swift 和 Objective-C 混合开发时,你会发现在 Objective-C 的代码里无法调用 Swift 的 Struct。因为要在 Objective-C 里调用 Swift 代码的话,对象需要继承于 NSObject。
2、继承
Struct 不能相互继承。
3、NSUserDefaults
Struct 不能被序列化成 NSData 对象。
如果模型较小,并且无需继承、无需储存到 NSUserDefault 或者无需 Objective-C 使用时,建议使用 Struct。
为什么访问struct比class快?
“堆”和“栈”并不是数据结构上的Heap(堆)跟Stack(栈),而是程序运行中的不同内存空间。栈是程序启动的时候,系统事先分配的,使用过程中,系统不干预;堆是用的时候才向系统申请的,用完了需要交还,这个申请和交还的过程开销相对就比较大了。
栈是编译时分配空间,而堆是动态分配(运行时分配空间),所以栈的速度快。
从两方面来考虑:
1.分配和释放:堆在分配和释放时都要调用函数(MALLOC,FREE),比如分配时会到堆空间去寻找足够大小的空间(因为多次分配释放后会造成空洞),这些都会花费一定的时间,而栈却不需要这些。
2.访问时间:访问堆的一个具体单元,需要两次访问内存,第一次得取得指针,第二次才是真正得数据,而栈只需访问一次。
objc中,数组是类,是引用类型,在Swift中,数组是结构体,是值类型
String 是结构体, 值类型, NSString 是类, 引用类型.
struct是值类型,class是引用类型。
值类型的变量直接包含它们的数据,对于值类型都有它们自己的数据副本,因此对一个变量操作不可能影响另一个变量。
引用类型的变量存储对他们的数据引用,因此后者称为对象,因此对一个变量操作可能影响另一个变量所引用的对象。
二者的本质区别:struct是深拷贝,拷贝的是内容;class是浅拷贝,拷贝的是指针。
property的初始化不同:class 在初始化时不能直接把 property 放在 默认的constructor 的参数里,而是需要自己创建一个带参数的constructor;而struct可以,把属性放在默认的constructor 的参数里。
变量赋值方式不同:struct是值拷贝;class是引用拷贝。
immutable变量:swift的可变内容和不可变内容用var和let来甄别,如果初始为let的变量再去修改会发生编译错误。struct遵循这一特性;class不存在这样的问题。
mutating function: struct 和 class 的差別是 struct 的 function 要去改变 property 的值的时候要加上 mutating,而 class 不用。
继承: struct不可以继承,class可以继承。
struct比class更轻量:struct分配在栈中,class分配在堆中