美文网首页
Swift结构体和类

Swift结构体和类

作者: 枫韵海 | 来源:发表于2018-04-09 21:41 被阅读9次

    最近在学习,顺便总结和记录一下

    结构体和类

    要说结构体和类就需要先说说值类型和引用类型了

    Swift的类型分为值类型和引用类型两种

    • 值类型: 在传递和赋值时进行复制,如struct,enum。所有内建类型(包括Int,Bool,String, Array, Dictionary)(OC和Swift区别之一)
    • 引用类型: 只会使用引用对象的一个“指向” ,如class

    类与结构体的主要相同点

    • 定义属性用于存储值。
    • 定义函数以提供功能。
    • 定义下标,以便用下标语法来访问它们的值。
    • 通过扩展来扩展它们的默认实现。
    • 利用协议来完成特定标准功能。

    类与结构体的主要不同点

    • 类:引用类型。 结构体: 值类型,在设计结构体时,我们可以要求编译器保证不可变性。
    • 内存的管理方式有所不同,类的实例只能通过引用来间接地访问。类能有很多个持有者.需要自己管理其引用计数、引用值得变化。 结构体可以被直接持有及访问,不会被引用,但是会被复制。也就是说,结构体的持有者是唯一的。
    • 类:可以继承,结构体(以及枚举): 不能被继承的。

    结构体的一些说明

    • 结构体只有一个持有者,所以它不可能造成引用循环。而对于类和函数这样的引用类型,我们需要特别小心,避免造成引用循环的问题。
    • 值总是需要复制这件事情听来可能有点低效,不过,编译器可以帮助我们进行优化,以避免很 多不必要的复制操作。因为结构体非常基础和简单,所以这是可能的。结构体复制的时候发生 的是按照字节进行的浅复制。除非结构体中含有类,否则复制时都不需要考虑其中属性的引用 计数。当使用 let 来声明结构体时,编译器可以确定之后这个结构体的任何一个字节都不会被改变。
    • 如果一个结构体只由其他结构体组成,那编译器可以确保不可变性。同样地,当使用结构体时,编译器也可以生成非常快的代码。举个例子,对一个只含有结构体的数组进行操作的效率,通常要比对一个含有对象的数组进行操作的效率高得多。这是因为结构体通常要更直接:值是直接存储在数组的内存中的。而对象的数组中包含的只是对象的引用。最后,在很多情况下,编译器可以将结构体放到栈上,而不用放在堆里。

    几个相关的名词

    值类型

    每个实例都保留了一分独有的数据拷贝,一般以结构体 (struct)、枚举(enum) 或者元组(tuple)的形式出现。

    值语义

    结构体只有一个持有者。比如,当我们将结构体变量传递给一个函数时,函数将接收到结构体的复制,它也只能改变它自己的这份复制。这叫做值语义,有时候也被叫做 复制语义。

    引用类型

    每个实例共享同一份数据来源,一般以类(class)的形式出现。

    引用语义

    而对于对象来说,它们是通过传递引用来工作的,因此类对象会拥有很多持有者, 这被叫做引用语义

    下面用代码来验证一下值类型和引用类型

    首先定义一个打印内存地址的函数

    // 打印对象内存地址
    func printAddress(values: AnyObject...) {
        for value in values {
          print(Unmanaged.passUnretained(value).toOpaque())
        }
        print("-----------------------------------------")
    }
    

    然后定义一个类和一个结构体

    class ObjectTest: NSObject {
        var t1 = 0
    }
    
    struct StructTest {
        var t1 = 0
    }
    

    给类和结构体分别赋值,打印下结果

    let objectTest = ObjectTest()
    let objectTest1 = objectTest
    objectTest1.t1 = 1
    print(objectTest.t1)
    print(objectTest1.t1)
    
    let structTest = StructTest(t1: 0)
    var structTest1 = structTest
    structTest1.t1 = 100
    print(structTest.t1)
    print(structTest1.t1)
    
    1
    1
    0
    100
    
    

    给其中一个类objectTest1的t1赋值,然后objectTest的t1随之发生改变,但是结构体structTest1只改变了当前自己的t1,而structTest的t1并没有发生改变。上面说了类和结构体分别是引用类型和值类型,也就是说引用类型和值类型对应发生上面的情况,值类型每个实例保留了一分独有的数据拷贝,而每个实例共享同一份数据来源

    验证, 打印结果

    printAddress(values: objectTest, objectTest1)
    printAddress(values: structTest as AnyObject, structTest1 as AnyObject)
    
    0x000060400001be60
    0x000060400001be60
    -----------------------------------------
    0x0000604000446000
    0x0000604000446030
    -----------------------------------------
    

    结论

    值类型复制的时候,两者的内存地址并不一样。相当于创造了一个完全独立的实例,这个实例保有属于自己的独有数据,数据不会受到其他实例的数据变化影响。值类型就好像身份证复印件一样,复印出来之后,修改原件上面的内容,复印件上的内容不会变。

    引用类型复制的时候,因为两者的内存地址是一样的。相当于默默地创造了一个共享的实例分身,两者是共用一套数据。因此修改其中任何一个实例的数据,也会影响到另外那个。

    相关文章

      网友评论

          本文标题:Swift结构体和类

          本文链接:https://www.haomeiwen.com/subject/udswhftx.html