一、与class的不同点
age给定默许值
/**结构体*/
struct FFHobbyGirls {
var age = 10
func hobbyGirls() {
print("hobbyGirls")
}
}
var t = FFHobbyGirls()
age不给定默许值
/**结构体*/
struct FFHobbyGirls {
var age: Int
func hobbyGirls() {
print("hobbyGirls")
}
}
var t = FFHobbyGirls(age: 10)
定论:
相对于class来说,struct会主动给定初始化方法,假如是class的情况下,会报错
二、假如我们的特点有默许的初始值,那么我们的系统就不会供给默许的初始化方法了
在SIL视点来分析一下原理:
翻开项目文件夹目录
cd /Users/zhou/Desktop/SwiftTwoPractice/SwiftTwoPractice
把 mian.swift编译成main.sil并翻开(举荐运用vs code)
swiftc -emit-sil main.swift | xcrun swift-demangle >> ./main.sil && open main.sil
No application knows how to open /Users/zhou/Desktop/SwiftTwoPractice/SwiftTwoPractice/main.sil.
来看main.sil,供给了两个初始化方法
init(age: Int = 10)
init()
struct FFHobbyGirls {
@_hasStorage @_hasInitialValue var age: Int { get set }
func hobbyGirls()
init(age: Int = 10)
init()
}
假如我自己完成了init方法
struct FFHobbyGirls {
var age = 10
func hobbyGirls() {
print("hobbyGirls")
}
init(age:Int) {
self.age = age
}
}
假如是这样的话,其时编译器就不会帮我生成init方法了,再次查看main.sil
struct FFHobbyGirls {
@_hasStorage @_hasInitialValue var age: Int { get set }
func hobbyGirls()
init(age: Int)
}
这个时分这里面就只有我们自己生成的初始化方法了
三、结构体是值类型
先了解什么是值类型:
比如:
func test() {
var age = 18
var age2 = age //设置断点 ①
age = 30 //设置断点 ②
age2 = 45
print("age=\(age),age2\(age2)")
}
var age = 18
意味着在栈区声明晰一个地址来存储age变量,然后将18这个字面量给到其时的地址空间
在栈区创建的内存空间是由系统办理的
经过lldb调试来查看age的地址,这个地址很明显是个栈上的地址空间(高地址)
(lldb) po withUnsafeMutablePointer(to: &age){print($0)}
0x00007ffeefbff410
0 elements
然后对这个内存进行格局化输出,在这个内存地址里面直接存储的我们的值18(0x0000000000000012 )
(lldb) x/8g 0x00007ffeefbff410
0x7ffeefbff410: 0x0000000000000012 0x0000000000000000
0x7ffeefbff420: 0x00007ffeefbff440 0x0000000100002a14
0x7ffeefbff430: 0x00007ffeefbff468 0x0000000100015025
0x7ffeefbff440: 0x00007ffeefbff458 0x00007fff20393621
当铺开设置的断点①,停留在断点②处的时分,将age赋值给了age2,同等于我直接把age里面的值18拿出来赋值给了age2,也就是说将18赋值给了age2
相同适用lldb调试看成果:
(lldb) po withUnsafeMutablePointer(to: &age2){print($0)}
0x00007ffeefbff408
0 elements
(lldb) po withUnsafeMutablePointer(to: &age){print($0)}
0x00007ffeefbff410
0 elements
可以看出,age与age2这两个地址只差了8字节巨细,栈空间地址分配的过程中是从高到低的,这也可以认证age是存储在栈上的
然后我在格局过输出age与age2的值:
(lldb) x/8g 0x00007ffeefbff408
0x7ffeefbff408: 0x0000000000000000 0x0000000000000012
0x7ffeefbff418: 0x0000000000000000 0x00007ffeefbff440
0x7ffeefbff428: 0x0000000100002a14 0x00007ffeefbff468
0x7ffeefbff438: 0x0000000100015025 0x00007ffeefbff458
(lldb) x/8g 0x00007ffeefbff410
0x7ffeefbff410: 0x0000000000000012 0x0000000000000000
0x7ffeefbff420: 0x00007ffeefbff440 0x0000000100002a14
0x7ffeefbff430: 0x00007ffeefbff468 0x0000000100015025
0x7ffeefbff440: 0x00007ffeefbff458 0x00007fff20393621
(lldb)
这个值也是相同的,在修正的过程中,修正的是其时独立地址里面的内存的值,也就意味着,在这个过程中,可以说age变量是一个值类型
相同的,看struct的比如:
struct FFHobbyGirls {
var age: Int = 18
var age2: Int = 20
}
//结构体再赋值的过程中并不会同享状况
var t = FFHobbyGirls()
print("end")
经过lldb调试查看:
(lldb) po t
▿ FFHobbyGirls
- age : 18
- age2 : 20
(lldb) po withUnsafeMutablePointer(to: &t){print($0)}
0x00000001000081a0
0 elements
(lldb) x/8g 0x00000001000081a0
0x1000081a0: 0x0000000000000012 0x0000000000000014
0x1000081b0: 0x0000000000000000 0x0000000000000000
0x1000081c0: 0x0000000000000000 0x0000000000000000
0x1000081d0: 0x0000000000000000 0x0000000000000000
可以看出,这个结构体的地址0x00000001000081a0中,直接存储的就是0x0000000000000012、0x0000000000000014,所以认证了结构体是值类型
注意点:尽量避免在值类型中包括引证类型