swift中let究竟能否保证变量不被修改

12 篇文章 0 订阅

先说结论,定长的值类型,可以保证;其他的(引用及非定长的值类型),不能保证

Swift中,常用let表示静态变量,不可变得;var表示动态变量,可变的。可事实往往并没有这么简单,还要从变量内存存储方式说起。


对于定长的值类型(字符串,集合类型都是变长的),如struct point,都是保存在栈中的,速度快,效率高,自动释放内存,很方便。变长的值类型,引用类型,这俩指针放在栈中间,但是具体的数据都是存放在堆中间的,速度慢一些,需要关心内存状况,但空间大,灵活。

对于存在栈中的变量,可以通过let对其进行限制,限制之后保证其实不可变得,更安全一些。


但对于存在堆中的变量, let只能保证其指针(也就是栈中的指针)不变,但对于指针指向的堆中的内存,是不能保证他的属性变量不变的,具体要看属性变量是可变的还是不可变的。如果是不可变的,能保证不能被修改,如果是可变的,就不能限制他被赋新值。当然,你可以把所有的成员变量都设置成let,这样确实能保证数形变量也不会改变,但这会带来新的问题,即如果你想修改某一成员变量,只能重新创建对象并赋值,这会带来一系列的操作,加锁,寻址,内存回收,耗时耗性能不说,程序也不美观。

综上,在编码层面上,值类型数据,可以将成员变量都设成var,这样如果想要一个静态变量,直接将值类型数据设置成let即可保证不被修改,如果需要修改,设置成var即可灵活修改,进退有度。

PS:swift语言默认的是不可变的状态,例如方法传入实参时会进行拷贝,拷贝之后的是不可变的。编码时声明的var变量如果没有修改其具体数值,编译器会提示是否修改成let。看来let肯定是速度更快一些的。

再进一步考虑,不能保证数据的不可变性,当赋值共享某可变数据时,就会产生问题,新的值修改,老的值也会一并被修改。这也不是一定不好,这能在一定程度上共享内存,提高效率,A改变,B自动改变,一定程度上更好的实现需求。但对于不愿意共享这一修改的时候,就会产生问题,类似于OC中浅拷贝,深拷贝区别。
如果想避免上述因共享带来的数据绑定的问题,可以使用copy()方法。比如用B对A进行赋值,如果直接是A=B,这是浅拷贝,会导致上述问题。如果A=B.copy(),是深拷贝,则不会导致上述问题。

以上确实能解决因为拷贝带来的共享的问题。其实不难发现,共享的问题是由于写入导致的,如果是多个变量同时读取同一变量,并不会出问题,但如果写入,就会出问题。因此苹果提出了Copy-on-Write的概念。简单说,就是在写入时自动copy,读取的话不作处理。举个栗子。如果A=B,AB共用一开始B的那一段内存。如果A只是读取,则直接读取B的地址中的数据就可以了。如果A写入了一些数据,则会自动copy出来一份,将需要写入的数据写入到新copy的内存中,并把新的地址赋给A,这样AB都能各自维护自己的数据了。具体代码网上一搜一大把

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值