Swift5.1学习随笔之值类型、引用类型

值类型

值类型赋值给var let或者给函数传参,是直接将所有内容拷贝一份
类似于对文件做copy paste操作,产生全新的文件副本,属于深拷贝deep copy

var p1 = Point(x: 10, y: 10)
var p2 = p1 //将p1的所有内容直接拷贝覆盖给p2,两个都在栈空间
    
p2.x = 11
p2.y = 22
//请问p1.x p1.y是多少

上面代码中的p1.x、p1.y的值依然是10、10p2的赋值不影响p1的值

值类型的赋值操作

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)
a1[0] = 2
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) // ["other": 7, "min": 2, "max": 10]
print(d2) //["min": 2, "max": 12]

swift标准库中,为了提升性能,String、Array、Dictionary、Set采取了Copy On Write的技术
当我们要修改内存的时候,才会进行深度拷贝操作。
下面的代码中,当s2没有做修改操作的时候,s1s2是共用一块内存地址。

var s1 = "jack"
var s2 = s1

引用类型

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

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)
var s2 = s1
//获得引用所指向内存的地址
print(Mems.ptr(ofRef: s1)) // 0x000000010043d510
print(Mems.ptr(ofRef: s2)) // 0x000000010043d510

// 修改了s1.width,同时s2.width的值也跟着变动
print(s2.width) // 10
s1.width = 100
print(s2.width) // 100

引用类型的赋值操作

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: 20, height: 30)

var s1 = Size(width: 10, height: 20)指向了堆空间的Size对象
s1 = Size(width: 20, height: 30)又重新指向了一个全新的Size对象

值类型、引用类型的let

来看一个结构体跟一个类的let常量初始化

struct Point {
    var x: Int
    var y: Int
}
let p = Point(x: 10, y: 20)
p = Point(x: 20, y: 30) //报错:Cannot assign to value: 'p' is a 'let' constant
p.x = 33 //报错:Cannot assign to property: 'p' is a 'let' constant
p.y = 44 //报错:Cannot assign to property: 'p' is a 'let' constant

值类型Point的常量p不允许重新指向其他对象,其内部的成员虽然是变量var类型,同样也不允许重新赋值

class Size {
    var width: Int
    var height: Int
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}
let s = Size(width: 10, height: 20)
s = Size(width: 20, height: 30) //报错:Cannot assign to value: 's' is a 'let' constant
s.width = 33 //编译通过
s.height = 44 //编译通过

引用类型Size的常量s不允许重新指向其他对象,但是其内部的成员是var变量类型,允许重新赋值修改

1、let代表ps是常量,内存都不允许修改。
2、p是结构体-值类型,它内存里面包含1020两个值,内存大小16个字节,同时内存不能改,所以这16个字节都不能改,所以修改了xy都会报错。
3、s是类-引用类型,由于是常量,所以s的内存不可以改,但是s是引用类型,s是一个指针变量,s的内存只占8个字节,代表着这8个字节不可以修改,相当于存放堆空间Size对象的地址值而已。然而s.width = 33s.height = 44修改的并不是s的内存,s依然指向自己的对象。

let str = "jack"
str.append("_Fuck") //报错:Cannot use mutating member on immutable value: 'str' is a 'let' constant

let arr = [1, 2, 3]
arr[0] = 11 //报错:Cannot assign through subscript: 'arr' is a 'let' constant
arr.append(4) //报错:Cannot use mutating member on immutable value: 'arr' is a 'let' constant

你可能感兴趣的:(Swift5.1学习随笔之值类型、引用类型)