首页 > 编程知识 正文

swift回归主线程,swift结构体可以继承吗

时间:2023-05-06 20:02:23 阅读:162655 作者:2876

一.结构初始化结构初始化:结构不需要定制初始化方法。 如果我们的属性有缺省初始值,编译器将提供不同的初始化方法。 如果我们定制初始化方法,编译器就不会为我们生成初始化方法。 1 .结构不需要定制初始化方法

因为编译器在结构体中移动组,所以可以合成初始化法:在SIL分析中进行查看。

创建对象时,必须执行以下初始化:

否则编译器报告错误

2 .如果我们的属性有默认初始值,编译器将提供不同的初始化方法

SIL分析

3 .定制初始化方法后,编译器不会为您生成初始化方法

类初始化如果不初始化类变量,编译器将直接报告错误

二、值类型和引用类型值类型是在分配给变量、常量或函数时将值复制到其中的类型。 实际上,Swift中的所有基本类型都是整数(integer )、浮点数、floating-point number、布尔值)、字符串(string )、数组(array )、字典(diction ) 这意味着这些实例以及实例中包含的值类型属性在通过代码传递时会被复制。 如果传递给变量、常量或函数,引用类型不会复制其值。 因此,使用对现有实例的引用,而不是副本。 首先,让我们看一下内存分区模型。 从下到上,分布如下。

堆栈区域:系统回收堆栈区域:看看不连续、链表形式的存储、访问案例、值类型变量地址

functestfunction((varage=20//堆栈区域varage2=ageage=30age2=40print ) ) age2=)、age2=) )。 (age2 ) ) }在此函数内部插入断点,并使用指针指定当前变量地址(lldb ) powithunsafemutablepointer ) to:age )0x 0007 ffee fbff 4400 elemement0x 00000007 fee fbff4owithunsafemutablepointer (to : age2) print ) $0) }0x00007ffeefbff4380elements ) lldb ) x/8g0x 00007 ffee fbff 4380 x7 ffee fbff 43833600 x 0000000000000 x 00000000000000 x 00000000000000000 x 00000000000 x 0000000000000 x 00000000000000000000000000000000000000000000000000000000000000000 00000000000 x 0000000000 3600 x 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ) ) ) 652 cat address0x 00007 ffee fbff 4400 x 00007 ffee fbff 440, stack address (sp :0 x7 ffee fbff 390 FP :0 x7 ffee fbff 450 ) hsstruct.testfunction(-) lldb ) cat address0x 00007 feffee 3600x7ffeefbff450 ) hsstruct.testfunction(-)由此,上述两个变量地址存储顺序为(从高到低; age和age2相差8个字节。 x/8g是以8段格式格式化输出存储器地址而得到的,存储在0x7ffeefbff438中的值为30,存储在下一段的地址0x7ffeefbff440中的值为40。 两者是显示安装了独立的cat address命令的内存分区的插件,由此可知当前的变量存在于堆栈区域。 加载方式一vim ~/.lld含蓄的密钥itplugin load ~/含蓄的密钥/libfooplugin (在用户根下制作含蓄的密钥文件,在其中放置libfooplugin插件. lld含蓄的. lld含蓄密钥it加载方式2 )如果上述方法不起作用,则在Xcode调试时,直接使用plugin load ~/含蓄密钥/libfooplugin,然后在插件加载方式3 )或Xcode )中

结果,t1=t代入进行值的复制,新复制了地址的情况下,两个变量相互独立; 因此,双方的修改不会改变彼此的数值。对比类来分析

classhsstudent { varage : int=18 varage 2: int=20 }//当前内存大小为32字节//引用类型: varT1=hsstudent(varT2=T1///

= 22//断点2print("end")//断点3 我们在控制台进行输出打印,可以得出结论 当在断点1,未进行赋值操作时、由于创建的类实例对象占32字节。当前0x100441bb0地址输出含0x100441bb0上的metadata 和refCounts。 0x100441bc0地址上存放的是类对象的存储值 18和20当在断点2时,进行了赋值操作,此时输出发现t2变量的地址还是引用的 t1变量的地址,并且地址上数据一致当在断点3时,我们对t2实例变量的数值进行了修改,此时修改之后,t1变量的值也随之改变。顾 t1 = t 创建的实例对象进行赋值操作时、并没有新开辟地址空间、修改时只是对其t原有地址上的值进行了修改。(lldb) po t1<HSStudent: 0x100441bb0>(lldb) x/8g 0x100441bb00x100441bb0: 0x0000000100008200 0x0000000200000002//metata refCounts0x100441bc0: 0x0000000000000012 0x00000000000000140x100441bd0: 0x0000000000000000 0x00000000000000000x100441be0: 0x0000000000000002 0x00020000100443e1(lldb) po t2<HSStudent: 0x100441bb0>(lldb) x/8g 0x100441bb00x100441bb0: 0x0000000100008200 0x00000006000000020x100441bc0: 0x0000000000000012 0x00000000000000140x100441bd0: 0x0000000000000000 0x00000000000000000x100441be0: 0x0000000000000002 0x00020000100443e1(lldb) x/8g 0x100441bb00x100441bb0: 0x0000000100008200 0x00000006000000020x100441bc0: 0x0000000000000016 0x00000000000000140x100441bd0: 0x0000000000000000 0x00000000000000000x100441be0: 0x0000000000000002 0x00020000100443e1(lldb) po t1<HSStudent: 0x100441bb0> 其实值类型和引⽤类型就像什么? ⼀个是在线表格,⼀个是本地的excel,当我和你共享编辑⼀个在线表格的时候其实就是⼀个引⽤类型,⽽当我们要通过QQ传给你⼀个excel的时候,这个时候就相当于⼀个 值类型,你修改的内容我是不知道的。

案例:值类型包含引用类型

class HSStudent{    var age:Int  = 18    var age2:Int = 20}struct HSTeacher{    var age:Int  = 18    var age2:Int = 20    var teach:HSStudent = HSStudent()   //引用类型}var t = HSTeacher() //值类型var t1 = t          //断点1、t.teach.age = 30    //断点2、print("(t1.teach.age)")//断点3、 30 断点1处获取当前实例对象的地址并格式化输出、值类型直接存储的数值,0x100008398地址存储的是teach变量。输出teach变量地址先得到HSStudent实例对象的地址及数值(lldb) po withUnsafeMutablePointer(to: &t){print($0)}0x00000001000083880 elements(lldb) x/8g 0x00000001000083880x100008388: 0x0000000000000012 0x00000000000000140x100008398: 0x000000010042c2e0 0x00000000000000000x1000083a8: 0x0000000000000000 0x00000000000000000x1000083b8: 0x0000000000000000 0x0000000000000000(lldb) x/8g 0x000000010042c2e00x10042c2e0: 0x0000000100008230 0x00000002000000020x10042c2f0: 0x0000000000000012 0x00000000000000140x10042c300: 0x0000000000000000 0x00000000000000000x10042c310: 0x0000000000000002 0x0002000010042e54 断点2处、新创建变量t1、因为t为值类型、所以t1应当开辟新空间 0x00000001000083a0 并且拷贝t实例变量的数值、然而其中的引用类型变量地址并没有进行值拷贝、还是引用了之前的地址 0x000000010042c2e0(lldb) po withUnsafeMutablePointer(to: &t1){print($0)}0x00000001000083a00 elements(lldb) x/8g 0x00000001000083a00x1000083a0: 0x0000000000000012 0x00000000000000140x1000083b0: 0x000000010042c2e0 0x00000000000000000x1000083c0: 0x0000000000000000 0x00000000000000000x1000083d0: 0x0000000000000000 0x0000000000000000(lldb) x/8g 0x000000010042c2e00x10042c2e0: 0x0000000100008230 0x00000004000000020x10042c2f0: 0x0000000000000012 0x00000000000000140x10042c300: 0x0000000000000000 0x00000000000000000x10042c310: 0x0000000000000002 0x0002000010042e54 断点3处、执行完t.teach.age后,值类型调用其中的引用类型并做了修改,理论上应该是另一片空间,与t1相互独立。然而t对teach.age的修改却改变了t1中teach.age的值。输出为30(lldb) x/8g 0x000000010042c2e00x10042c2e0: 0x0000000100008230 0x00000004000000020x10042c2f0: 0x000000000000001e 0x00000000000000140x10042c300: 0x0000000000000000 0x00000000000000000x10042c310: 0x0000000000000002 0x0002000010042e54 因此我们在实际使用中、应该避免值类型中包含引用类型、否则值类型调用其中的引用类型进行修改、其他新建的实例变量也会访问到修改后的值。三、mutating&inout使用 mutating:实例方法中是不可以修改值类型的属性,使用mutating后可修改属性的值;值类型本身创建之后是不允许修改,如果要修改,需要使⽤ mutating 关键字;案例分析:如果我们想实现这样一个函数时、编译器报错struct LGStack {    var items = [String]() //_ 外部参数 //item 内部参数    func push(_ item:String){        items.append(item)//Cannot use mutating member on immutable value: 'self' is immutable //jwdxf method 'mutating' to make 'self' mutable    }} items本质上是self.items; 省略了self。我们查看func内部self类型struct LGStack {    var items = [String]()    func push(_ item:String){        print(item)    }} 通过上述代码终端执行SIL分析及命名重整还原得到SIL底层实现、当前func内部的self为let 常量类型、因此不可修改。

而使用mutating关键字修饰了最开始案例的func之后、再查看SIL底层实现则看到、我们的self变成了var变量类型

2. 函数声明中:默认的参数不可变,为let类型、我们通过如下案例可见、注释部分为编译器报错

func swap(_ a:Int ,_ b:Int){    let temp = a        a    = b//Cannot assign to value: 'a' is a 'let' constant        b    = temp//Cannot assign to value: 'b' is a 'let' constant} 查看SIL底层可见

此时我们引入关键字 inout: 传递地址的方式修改函数传参过程中的内部参数、并且传递的参数本身得为变量

在修改为变量后、可见实现了参数交换

此时查看我们的SIL底层、可以看到 传递的内部参数已变为var类型并且对该参数取地址运算

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。