小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
类的常用写法
//****** 写法一 *******
class CJLTeacher {
var age: Int = 18
func teach(){
print("teach")
}
init(_ age: Int) {
self.age = age
}
}
var t = CJLTeacher.init(20)
//****** 写法二 *******
class CJLTeacher {
var age: Int?
func teach(){
print("teach")
}
init(_ age: Int) {
self.age = age
}
}
var t = CJLTeacher.init(20)
在类中,如果属性没有赋值,也不是可选项,编译会报错
为什么类是引用类型?
定义一个类,通过一个例子来说明
class CJLTeacher1 {
var age: Int = 18
var age2: Int = 20
}
var t1 = CJLTeacher1()
类初始化的对象t1,存储在全局区
- 打印t1、t:
po t1,从图中可以看出,t1内存空间中存放的是地址,t中存储的是值
获取t1变量的地址,并查看其内存情况
- 获取
t1指针地址:po withUnsafePointer(to: &t1){print($0)} - 查看t1全局区地址内存情况:
x/8g 0x0000000100008218 - 查看t1地址中存储的堆区地址内存情况:
x/8g 0x00000001040088f0
引用类型 特点
- 1、地址中存储的是
堆区地址 - 2、
堆区地址中存储的是值
问题1:此时将t1赋值给t2,如果修改了t2,会导致t1修改吗?
- 通过
lldb调试得知,修改了t2,会导致t1改变,主要是因为t2、t1地址中都存储的是同一个堆区地址,如果修改,修改是同一个堆区地址,所以修改t2会导致t1一起修改,即浅拷贝
问题2:如果结构体中包含类对象,此时如果修改t1中的实例对象属性,t会改变吗?
代码如下所示
class CJLTeacher1 {
var age: Int = 18
var age2: Int = 20
}
struct CJLTeacher {
var age: Int = 18
var age2: Int = 20
var teacher: CJLTeacher1 = CJLTeacher1()
}
var t = CJLTeacher()
var t1 = t
t1.teacher.age = 30
//分别打印t1和t中teacher.age,结果如下
t1.teacher.age = 30
t.teacher.age = 30
从打印结果中可以看出,如果修改t1中的实例对象属性,会导致t中实例对象属性的改变。虽然在结构体中是值传递,但是对于teacher,由于是引用类型,所以传递的依然是地址
同样可以通过lldb调试验证
- 打印t的地址:
po withUnsafePointer(to: &t){print($0)} - 打印t的内存情况:
x/8g 0x0000000100008238 - 打印t中teacher地址的内存情况:
x/8g 0x000000010070e4a0
注意:在编写代码过程中,应该尽量
避免值类型包含引用类型