iOS之swift中的值类型

343 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

我们通过一个例子来引入什么是值类型

func test(){
    //栈区声明一个地址,用来存储age变量
    var age = 18
    //传递的值
    var age2 = age
    //age、age2是修改独立内存中的值
    age = 30
    age2 = 45
    
    print("age=(age),age2=(age2)")
}
test()

从例子中可以得出,age存储在栈区

  • 查看age的内存情况,从图中可以看出,栈区直接存储的是

    • 获取age的栈区地址:po withUnsafePointer(to: &age){print($0)}
    • 查看age内存情况:x/8g 0x00007ffeefbff3e0

1.1.jpg

  • 查看age2的情况,从下图中可以看出,age2的赋值相当于将age中的值拿出来,赋值给了age2。其中age 与 age2 的地址 相差了8字节,从这里可以说明栈空间是连续的、且是从高到低

1.2.jpg 所以,从上面可以说明,age就是值类型

值类型 特点

  • 1、地址中存储的是
  • 2、值类型的传递过程中,相当于传递了一个副本,也就是所谓的深拷贝
  • 3、值传递过程中,并不共享状态

结构体

结构体的常用写法

//***** 写法一 *****
struct CJLTeacher {
    var age: Int = 18
    
    func teach(){
        print("teach")
    }
}
var t = CJLTeacher()

//***** 写法二 *****
struct CJLTeacher {
    var age: Int
    
    func teach(){
        print("teach")
    }
}
var t = CJLTeacher(age: 18)
  • 在结构体中,如果不给属性默认值,编译是不会报错的。即在结构体中属性可以赋值,也可以不赋值
  • init方法可以重写,也可以使用系统默认的

为什么结构体是值类型?

定义一个结构体,并进行分析

struct CJLTeacher {
    var age: Int = 18
    var age2: Int = 20
}
var  t = CJLTeacher()
print("end")

打印t:po t,从下图中可以发现,t的打印直接就是值,没有任何与地址有关的信息

1.3.jpg

  • 获取t的内存地址,并查看其内存情况
    • 获取地址:po withUnsafePointer(to: &t){print($0)}
    • 查看内存情况:x/8g 0x0000000100008158

1.4.jpg 问题:此时将t赋值给t1,如果修改了t1,t会发生改变吗?

  • 直接打印t及t1,可以发现t并没有因为t1的改变而改变,主要是因为因为t1t之间是值传递,即t1和t是不同内存空间,是直接将t中的值拷贝至t1中。t1修改的内存空间,是不会影响t的内存空间的

1.5.jpg

总结

  • 结构体是值类型,且结构体的地址就是第一个成员的内存地址
  • 值类型
    • 在内存中直接存储值
    • 值类型的赋值,是一个值传递的过程,即相当于拷贝了一个副本,存入不同的内存空间,两个空间彼此间并不共享状态
    • 值传递其实就是深拷贝