【Swift学习】值类型、引用类型 & 堆、栈

上一篇博客中介绍了结构体与类,而两者比较重要的差异之一就是它们的类型不同,本文将会详细讲述这两种类型。


值类型(Value types) & 引用类型(Reference types)


在Swift中类型其实就分为两类:


值类型(Value types): 每个实例都保留一份独有的数据拷贝,一般以结构体 (struct) 、 枚举(enum) 或者元组(tuple)的形式出现。

引用类型(Reference types): 每个实例共享一份数据来源,一般以类(class)的形式出现。

(定义来自Apple Swift Blog: https://developer.apple.com/swift/blog/?id=10)


具体是什么意思呢?看看下面的例子就明白了。



引用类型(Reference types)


创建一个Person类,里面有一个name属性:


class Person {
    var name: String

    init(name: String) {
        self.name = name
    }
}

var var1 = Person(name: "John")


此时,var1在内存中是这样的:



创建一个新的变量var2让它等于var1:

var var2 = var1


此时,var1 和 var2 指向了内存中的同一个地方:



上文我们说class是引用类型,顾名思义,"引用"就是C语言中的指针,指针是一个地址,指向某个内存,因此类的变量实际上是存储了实例的地址,当我们声明一个新的变量var2 = var1时,并没有创建一个新的实例,而是把var1实例的地址赋值给var2,于是就有了图2。


知道了类实例的存储机制,下面这种现象就非常容易理解了:

var1.name = "Jane"

print(var1.name)   // Jane
print(var2.name)   //Jane
我们只改变了变量var1的name属性,发现var2的name属性也发生了变化。原因非常明显,因为var1和var2是共享同一个实例,当使用变量var1修改了其所指向的实例之后,var2对应的实例自然也就被修改了。



值类型(Value types)


同样的,我们以struct为例来说明值类型:


创建一个Person结构体,里面有一个name属性:

struct Person {
    var name: String
}

var var1 = Person(name: "John")


此时,var1中存储的不是指向内存的指针,而是值:



创建一个新的实例var2,并赋值为var1:

var var2 = var1


此时,系统将会创建一个新的实例并将var1中的值拷贝一份,如下图所示:



因此,当修改var1中的属性时,var2的值是不会发生改变的:

var1.name = "Jane"

print(var1.name)   //Jane
print(var2.name)   //John
可以看到var2还是保持原来的值,因为在执行var2 = var1时,系统拷贝了一个新的实例给var2,那么var1与var2之间是不会相互影响的。


值类型和引用类型有各自的优缺点,我们应该根据具体的需求来选择。




堆(heap) & 栈(stack)


堆和栈是内存中不同的分区,它们与引用类型和值类型有很多的联系。


栈(Stack):当我们创建一个值类型,如结构体,系统将其存储在一个被称为栈的内存区域中。系统使用栈来存储在紧急线程上的任何东西,是由CPU直接管理和优化的。当一个函数声明一个变量,变量将存储在栈中,当函数调用完毕后栈会自动释放该变量。因此栈是非常易于管理的、有效的,由于是CPU直接控制,速度非常快。


堆(Heap):当我们创建了一个引用类型,如类,系统将把类实例存储在一个被称为堆的内存区域中。系统使用堆来存储其他对象引用的数据。堆是一个大的内存池,系统可以从该池中请求并动态分配内存块。堆不会像栈一样自动释放对象,需要额外的工作来完成。这使得在堆中创建和删除数据比栈慢。


下图展示了类的实例在堆和栈中的存储:


当我们创建一个类的实例时,系统会在堆中申请一个内存块用于存储实例本身,如图中右边Heap中的两个实例。同时将把存储该实例的变量和堆中的地址存储在栈中,如图的左边所示。


而当创建一个结构体时,将会把变量和值都存储在栈中。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值