美文网首页
结构体 & 类

结构体 & 类

作者: 曹来东 | 来源:发表于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修饰不能被修改

相关文章

  • 第九章 类和结构体

    c++中,结构体是稍有不同的类,类能做的,结构体也可以; 而swift中,结构体与类有较大区别, 结构体与类的区别...

  • 类和结构体

    类与结构体 本节内容包括: 类和结构体对比 结构体和枚举是值类型 类是引用类型 类和结构体的选择 集合类型的赋值与...

  • Swift笔记<十五>结构体和类的区别

    结构体和类的区别 结构体有逐一构造器,类没有 结构体是值类型,类是引用类型 结构体不是继承(意味着没有多态)

  • swift基础_结构体和类

    一.结构体和类 结构体张这个样子 类张这个样子 二.结构体和类的区别 针对结构体, 即使你没有定义函数,编译器也会...

  • Swift5 _07_多态原理_初始化

    多态 结构体struct与类class 的区别(1)结构体是值类型、类是引用类型(2)类可以继承,结构体不能继承(...

  • Swift学习_基本语法之枚举&类&结构体

    1.枚举 类和结构体 在swift中类和结构体类似,可以把结构体理解成是一种轻量级的类,在swift中结构体不仅可...

  • Swift Tour Learn (六) -- Swift 语法

    Swift语法基础(五)-- (类和结构体、属性、方法) 本章将会介绍 类和结构体对比结构体和枚举是值类型类是引用...

  • Swift 面向对象 2: 结构体

    1.结构体: swift中的结构体和类非常相似,也就是结构体能实现类的全部操作(功能)结构体是值类型,类是引用类型...

  • 结构体和类的一些简单区别

    结构体和类的区别 1.写法区别: 结构体-struct 类-cl...

  • C#结构体,析构方法,跨程序访问

    结构体 结构体定义 结构体的语法格式: struct + 结构体名 { 结构体成员变量(相当于类中的字段) } 结...

网友评论

      本文标题:结构体 & 类

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