美文网首页
结构体 & 类

结构体 & 类

作者: 曹来东 | 来源:发表于2019-06-28 17:59 被阅读0次
    • 在Swift标准库中,绝大多数的公开类型都是结构体,而枚举和类只占很小一部分.
    • 比如Bool Int Double String Array Dictionary等常见类型都是结构体
    • 所有的结构体都有一个编译器自动生成的初始化器(initializer,初始化方法,构造器,构造方法)
    • 可以传入所有成员值,用以初始化所有成员(存储属性,Stored Property)
    struct Date {
        var year: Int
        var month: Int
        var day: Int
    }
    var date = Date(year: 2019, month: 6, day: 28)
    

    结构体初始化器

    • 编译器会根据情况,可能会为结构体生成多个初始化器,宗旨是:保证所有成员都有初始值.
    
    struct Point {
        var x: Int = 0
        var y: Int = 0
    }
    
    let p1 = Point(x: 10, y: 10);
    let p2 = Point(x: 10)
    let p3 = Point(y: 9)
    let p4 = Point()
    
    struct Point {
        var x: Int?
        var y: Int?
        
    }
    var p1 = Point(x: 10, y: 1)
    var p3 = Point(x: 4)
    var p3 = Point(y: 4)
    var p4 = Point()
    

    以上代码可以在Xcode11上编译通过.因为每个成员变量都有初始值nil

    结构体内存

    struct Point {
        var x: Int = 0
        var y: Int = 0
        var origin: Bool = false
     
    }
    print(MemoryLayout<Point>.size)//17
    print(MemoryLayout<Point>.stride)//24
    print(MemoryLayout<Point>.alignment)//8
    

    • 类的定义与结构体类似,但编译器并没有为类自动生成可以传入成员值的初始化器。
    class Point {
        var x: Int = 0
        var y: Int = 0
    }
    let p4 = Point()
    let p1 = Point(x: 10, y: 10);
    let p2 = Point(x: 10)
    let p3 = Point(y: 9)
    
    image.png
    image.png

    类的初始化器

    • 如果类的所有成员都在定义的时候指定了初始化知,编译器会为类生成无参的初始化器
    • 成员的初始化是在这个初始化器中完成的
    class Point {
        var x: Int
        var y: Int 
        init() {
            x = 0
            y = 0
        }
    }
    let p4 = Point()
    
    
    class Point {
        var x: Int = 0
        var y: Int = 0
    }
    let p4 = Point()
    
    

    以上代码是完全等效的。

    结构体与类的本质区别

    • 结构体死是值类型(枚举也是值类型),类是引用类型(指针类型)
    struct Point {
        var x: Int = 3
        var y: Int = 4
    }
    class Size {
        var width = 1
        var height = 2
    }
    func test() {
        var size = Size()
        var point = Point()
    }
    
    image.png

    类的存储在堆空间,其中存储着类的 类型信息,引用计数 和成员变量的值。

    值类型

    • 值类型赋值给var ,let或者给函数传参,是直接将所有内容拷贝一份
    • 类似对文件进行copy,paste操作,产生了全新的文件副本,属于深拷贝(depp copy)
    struct Point {
        var x: Int = 3
        var y: Int = 4
    }
    
    func test() {
        var p1 = Point(x: 10, y: 1)
        var p2 = p1
    }
    
    image.png
    p2.x = 99
    p2.y = 777
    //修改p2对p1没有影响,因为是两个完全独立的内存操作
    

    值类型的赋值操作

    • Swift标准库中,为了提升性能,String Array Dictionary Set采取了Copy On Write的技术
    • 比如仅当有操作时,才会真正执行拷贝操作
    • 对于标准库值类型的赋值操作, Switf能确保最佳性能,所以没必要为了保证最佳性能 来避免赋值
    • 建议:不需要修改的,尽量定义成let
    var s1 = "Jack"
    var s2 = s1
    s2.append("_Rose")
    print(s1)//Jack
    print(s2)//Jack_Rose
    
    var a1 = [1,2,3]
    var a2 = a1
    a2.append(4)//[1,2,3,4]
    a1[0] = 2//[2,2,3]
    print(a1)//[2,2,3]
    print(a2)//[1,2,3,4]
    
    var d1 = ["max" : 10, "min" : 2]
    var d2 = d1
    d1["Other"] = 7
    d2["max"] = 12
    print(d1)//["max" : 10, "min" : 2,"Other" : 7]
    print(d2)//["max" : 12, "min" : 2]
    
    

    引用类型

    • 引用赋值给var let或者给函数传参,是将内存地址拷贝一份
    • 类似与制作一个文件的替身(快捷方式,链接),指向的是同一个文件,属于浅拷贝(shallow copy)
    class Point {
        var x: Int = 0
        var y: Int = 0
        init(x: Int, y: Int) {
            self.x = x
            self.y = y
        }
    }
    
    func test() {
        let p1 = Point(x: 10, y: 22)
        let p2 = p1
        
        p2.x = 55
        p2.y = 66
        
        print(p1.x)//55
        print(p1.y)//66  
    }
    
    image.png

    对象的堆空间申请过程

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

    引用类型的赋值操作

    class Size {
        var width: Int
        var height: Int
        init(width: Int,height: Int) {
            self.width = width
            self.height = height
        }
        
    }
    
    var s1 = Size(width: 10, height: 20)
    s1 = Size(width: 33, height: 55)
    
    image.png

    值类型 引用类型的let

    class Size {
        var width: Int
        var height: Int
        init(width: Int,height: Int) {
            self.width = width
            self.height = height
        }
        
    }
    
    let s1 = Size(width: 10, height: 20)
    s1 = Size(width: 33, height: 55)//报错,s1被let修饰不能被修改
    s1.width = 33
    s1.width = 44
    
    struct Point {
        var x: Int
        var y: Int
    }
    
    let p = Point(x: 10, y: 33)
    p = Point(x: 00, y: 99)//报错,p被let修饰不能被修改
    p.x = 77//报错,p被let修饰不能被修改
    p.y = 77//报错,p被let修饰不能被修改
    

    相关文章

      网友评论

          本文标题:结构体 & 类

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