Swift小知识点之 类

前言

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

 如下代码不会报错

struct Point {
    var x: Int = 0
    var y: Int = 0 
}
let p1 = Point()
let p2 = Point(x: 10, y: 20)
let p3 = Point(x: 10)
let p4 = Point(y: 20)

但是如果改成了类就不能编译通过

class Point {
    var x: Int = 0
    var y: Int = 0
}
let p1 = Point()
let p2 = Point(x: 10, y: 20)//报错Argument passed to call that takes no arguments
let p3 = Point(x: 10)//报错Argument passed to call that takes no arguments
let p4 = Point(y: 20)//报错Argument passed to call that takes no arguments

结构体与类的本质区别

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

    我们有如下的结构体point 和类 size

    // 类size
    class Size {
        var width = 1
        var height = 2
    }
    
    // 结构体Point
    struct Point {
        var x = 3
        var y = 4
    }
    
    // 变量 size 接收类Size
    var size = Size()
    // 变量 point 接收结构体point
    var point = Point()

我们假设 执行完test() 之后,point的内存地址为 0x10000 size的内存地址为 0x10010 可以用一幅图来表示

 

上图表示,point是值拷贝,直接把 3 和 4 放在了point对应的内存中,而 指针变量size是引用拷贝,是放了 Size() 的指针 0x90000 ,而对应的 堆空间 0x90000中才真正的存放1和2,

当然了,前面有16个字节,存放了类的信息,和引用计数,因为Swift和OC一样使用的引用计数来内存管理的,所以Size对象用了32个字节

对象的堆空间申请过程

  • 在Swift中,创建类的实例对象,要向堆空间申请内存,大概流程如下
    Class.__allocating_init() 
    libswiftCore.dylib:_swift_allocObject_ 
    libswiftCore.dylib:swift_slowAlloc 
    libsystem_malloc.dylib:malloc
  • 在Mac、iOS中的malloc函数分配的内存大小总是16的倍数
  • 通过class_getInstanceSize可以得知:类的对象至少需要占用多少内存
    class Point  {
        var x = 11
        var test = true
        var y = 22 
    }
    var p = Point() 
    class_getInstanceSize(type(of: p)) // 40
    class_getInstanceSize(Point.self) // 40

值类型 & 引用类型含义

  • 值类型

    • 值类型赋值给var、let或者给函数传参,是直接将所有内容拷贝一份

    • 类似于对文件进行copy、paste操作,产生了全新的文件副本。属于深拷贝(deep copy)

    • 在Swift标准库中,为了提升性能,String、Array、Dictionary、Set采取了Copy On Write的技术

      • 比如仅当有“写”操作时,才会真正执行拷贝操作
      • 对于标准库值类型的赋值操作,Swift 能确保最佳性能,所有没必要为了保证最佳性能来避免赋值
    • 建议:不需要修改的,尽量定义成let

  • 引用类型

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

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

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

  • 类中定义方法

    class Size {
        var width = 10
        var height = 10
        func show() {
            print("width=\(width), height=\(height)")
        }
    }
    let s = Size()
    s.show() // width=10, height=10
  • 结构体中定义方法

    struct Point {
        var x = 10
        var y = 10
        func show() {
            print("x=\(x), y=\(y)")
        }
    }
    let p = Point()
    p.show() // x=10, y=10
  • 枚举中定义方法

    enum grade : Character {
        case a = "a"
        case b = "b"
        func show() {
            print("res is \(rawValue)")
        }
    }
    let g = grade.a
    g.show() // res is a

     

posted on 2021-04-22 18:44  梁飞宇  阅读(173)  评论(0)    收藏  举报