Swift - 5 结构体、类的内存布局 区别

结构体

在Swift标准库中,绝大多数的公开类型都是结构体,而枚举和类只占很小的一部分

比如:Bool、Int、Double、String、Array、Dictionary等常见类型都是结构体

struct Date {
    var year: Int
    var mouth: Int
    var day: Int
}

var date = Date(year: 2019, mouth: 4, day: 2)

所有的结构体都有一个编译器自动生成的初始化器(initializer,初始化方法、构造器、构造方法) 上面最后一行调用的 可以传入所有成员值,用以初始化所有成员(存储属性,stored property)

结构体的初始化器

编译器会根据情况,可能会为结构体生成多个初始化器,宗旨是:保证所有成员都有初始值

思考:下面的代码能通过编译么?

struct Point {
    var x: Int?
    var y: Int?
}

var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
var p3 = Point(x: 10)
var p4 = Point()

可选项都有一个默认值nil,所以上面代码都可以编译通

自定义初始化器

一旦在定义结构体时自定义了初始化器,编译器就不会再帮他自动生成其他初始化器 所以如果你调用的话只有自己写的那个初始化器可以调用,其他原来系统帮你创建的现在都不会帮你创建了。

struct Point {
    var x: Int?
    var y: Int?
    init(x: Int?, y: Int?) {
        self.x = x
        self.y = y
    }
}

窥探初始化器的本质

以下2段代码完全等效

结构体内存结构

类的定义和结构体类似,但编译器并没有为类自动生成可以传入成员值的初始化器

类的初始化器

如果类的所有成员都在定义的时候指定了初始值,编译器会为类生成无参的初始化器,成员初始化是在这个初始化器中完成的

这两端代码完全相等

结构体和类的本质区别

结构体是值类型(枚举也是值类型),类是引用类型(指针类型)

对象的堆空间申请过程

在Swift中,创建类的实例对象,要向堆空间申请内存,大致流程如左图

值类型

值类型赋值给var、let或者给函数传参,是直接将所有内容拷贝一份,类似于对文件进行copy、paste操作,产生了全新的文件副本。属于深拷贝(deep copy)

值类型的赋值操作

你自定定义的结构体是没有提升性能的,只会深拷贝

在Swift标准库中,为了提升性能,String、Array、Dictionary、Set采取了Copy On Write。比如仅当有“写”操作时。才会真正执行拷贝操作,对于标准库类型的赋值操作,Swift能保证最佳性能,所以没有必要为了保证最佳性能来避免赋值,建议:不需要修改的,尽量定义成let。

struct Point {
    var x: Int
    var y: Int
}

var p1 = Point(x: 10, y: 10)
p1 = Point(x: 12, y: 13)

引用类型

引用类型赋值给var、let或者给函数传参,是讲内存地址拷贝一份。类似于只做一个文件的替身(快捷方式、链接)。指向的是同一个文件,属于浅拷贝(shallow copy)

值类型和引用类型的let

struct内容不可改,在栈区,class指向的var的可改,let的不可改,在堆区。

枚举、结构体、类都可以定义方法

一般吧定义在枚举、结构体、类内部的 函数,叫做方法

类和结构体的区别和联系:这是总结,以后可能会有相同的都是细节

区别1:

             在 ** swift ** 中,包含三种类型(type): ** structure ** , ** enumeration ** , ** class **

            其中structure和enumeration是值类型( ** value type ** ),class是引用类型( ** reference type ** )

区别2:

初始化:(没有自建的初始化器时)所有的结构体都有一个编译器自动生成的初始化器(initializer,初始化方法、构造器、构造方法)  可以传入所有成员值,用以初始化所有成员

                 类:编译器并没有为类自动生成可以传入成员值的初始化器

区别3:

               值类型,存放在栈区(stack)struct内容不可改;引用类型,存放在堆区(heap)class指向的var的可改,let的不可改

区别4:

            值类型,即每个实例保持一份数据拷贝。值类型的赋值为深拷贝(Deep Copy)

            引用类型,即所有实例共享一份数据拷贝,class 和闭包是引用类型。引用类型的赋值是浅拷贝(Shallow Copy)

区别5:

           类调用的方法和属性在修饰上,struct只能用static,而class可以用static,也可以用class。(static修饰的类方法不能继承,class修饰的类方法可以继承)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值