第五节 结构体、类、值类型、引用类型
2021-01-31 本文已影响0人
天明天
一. 结构体
1.在swift的标准库中绝大多数公开类型都是结构体,而枚举与类占很小一部分。
-
Bool,Int,Double,String,Array,Dictionary
等常见类型都是结构体。 - 自己创建结构体
struct Date {
var year:Int //存储属性
var month:Int
var day:Int
}
var date = Date(year:2020,month:02,day:26)//初始化成员
- 所有的结构体都有一个编译器自动生成的初始化器(initialize 、 初始化方法、构造方法、构造器)
- 结构体的初始化器
-
编译器可能会为结构体生成多个初始化器,宗旨:保证结构体的所有成员变量都有初始值。
Ex:
截屏2020-02-26上午10.27.14.png - 如果存储属性有初始值,可以不用初始化它。
- 结构体存在可选项的属性初始化
struct Student{
var name: String?
var age : Int?
}
var stu = Student(name:"chen",age:16)//初始化方法
var stu = Student() //初始方法 两个方法都可以
var stu = Student("name")
- 自定义初始化器
- 如果你自己自定义初始化器后,编译器不会再给你生成。
struct Point {
var x :Int
var y : Int
init(x: Int,y:Int){
self.x = x
self.y = y
}
}
var p1 = Point(x : 10, y : 20)
-
初始化器的本质,一下两段代码完全等效:
截屏2020-02-26上午10.39.01.png - 占用内存:
print(MemoryLayout<Point>.size)//16字节
print(MemoryLayout<Point>.stride)//16
print(MemoryLayout<Point>.alignment)//8
二.类
1.类基础
- 类的定义与结构体是类似的,但是编译器没有为类自动生成可以传入成员变量的初始化器。
class Point {
var x: Int = 0 // 这里要给初始化值
var y : Int = 0
}
var p = Point()//无参数的初始化器可以调用成功。
-
如果类的所有成员都有初始化值,编译器会为我们生成无参数的初始化器。
截屏2020-02-26上午11.08.51.png
2.结构体与类的本质区别
-
结构体 是值类型,与枚举类似。类是引用类型(指针类型)
截屏2020-02-26上午11.16.22.png -
Size
class 存储在 内存的 堆空间(即:汇编有没有调用 alloc,malloc方法开辟空间),Point
struct 存储在栈空间 -
查看 对象的占用内存空间大小:
导入import Foundation
func textP&S{
class Size{
var width = 1
var height = 2
}
Struct Point{
var x = 3
var y = 4
}
}
var ptr = malloc(1)
print(malloc_size(ptr)) //分配给16字节
*在 Mac 与 IOS 中 系统分配内存的大小 都是16的倍数。
3.值类型
- 值类型,赋值给 var ,let 或者给函数传值,是直接将所有 内容 拷贝一份,类似于对文件进行 copy,这个是 深拷贝。
截屏2020-02-26下午2.59.55.png
此时, p1.x = 10, p1.y = 20. P1 不受影响。 -
汇编规律:
截屏2020-02-26下午3.09.42.png - 值类型的 赋值操作:
-
String
,Array
,Dictionary
等都是值类型
var s1 = "123"
var s2 = s1
s2.append("234")
print(s1)//返回“123”
print(s2)// 123234
- 当编译器 有写入操作时候,才会进行真的的拷贝动作。
- 不需要修改的 需要定义成
let
4. 引用类型 (类)
- 引用类型给var、let 赋值或者传参时,是将 内存地址 拷贝一份
-
类似于制作一个文件替身(快捷方式、链接),指向同一个文件,属于浅拷贝。
截屏2020-02-26下午3.36.41.png
- 引用类型的赋值操作 浅拷贝,指向的内存地址是一样的
5.值类型、引用类型的 let
struct Point {
var x: Int
var y: Int
}
class Size {
var width:Int
var height:Int
init(width :Int,height:Int){
self.width = width
self.hieght = height
}
}
截屏2020-02-26下午6.03.49.png
- 注意这里的区别:
let 结构体: 指针跟成员都不能改变
let 类: s 本身的指针(内存)不能改变,但是成员能改变。 -
获取 类本身占用多少内存的方法
截屏2020-02-26下午6.15.10.png -
class_getInstanceSize(Point.self)
//后面加类型,或者class_getInstancellSize(type(of : p))
//这里 p是对象,返回40,表示至少需要分配多少字节。
6.嵌套类型
截屏2020-02-26下午6.23.27.png三.方法,枚举、结构体、类里面都可以定义方法
1.在外部的方法函数,在枚举、结构体、类里面 的函数就叫做方法。
- 内部方法在调用时,需要先实例化对象。
-
函数、方法都存贮在代码区
,不会存在类、结构体里面。