Swift5.9中的NonCopyable类型

325 阅读2分钟

前言

Swift5.9中引入了很多重大的更新,本篇文章是介绍其中的NonCopyable类型。

NonCopyable是适用于struct和enum的概念。和Swift中默认的类型不一样,Swift中未被NonCopyable修饰的类型在赋值、作为函数参数传递、作为函数返回值返回时默认是进行copy操作的。而NonCopyable只有一个所有者,和Rust中的所有者概念类似

已经有了class类型,为什么还需要NonCopyable类型?

class代表了唯一的资源,一个class初始化后,指向这个对象的引用持有这份资源。然后引用这个对象的引用依然是copyable,所以类所代表的资源是共享所有权的,这会导致一系列复杂的问题,堆分配、引用计数的复杂性和共享所有权的复杂性

这些则是NonCopyable处理的场景。NonCopyable只有单一所有权并且不会被复制

怎么声明NonCopyable类型

struct Vehicle: ~Copyable {  
    var name: String  
    var type: String  
}

包含NonCopyable属性的类也必须是NonCopyable的 image.png

NonCopyable不能应用到下面的类型上

  1. protocols
  2. generic parameters
  3. associated type requirements in protocols
  4. the Self type in a protocol declaration, or in extensions

NonCopyable作为函数参数必须指明所有权的处理方式

image.png 和Rust中一样,在Swift中对所有权的处理的方式也有三种

  1. 所有权转移,这可以使用 consuming 关键字。在调用printVehicle时newVehicle的所有权就转移到了printVehicle 函数的vehicle参数上。后面在createVehicle中对newVehicle的属性修改会报错

image.png

但由于newVehicle我们使用var修饰,它是一个变量,因此它依然可以指向新的值。只是说继续使用原来的值是不可以的

image.png

  1. 不可变借用,这可以使用 borrowing 关键字。borrowing修饰后参数即是let,不可修改。createVehicle拥有newVehicl的所有权,而printVehicle只是临时借用了所有权

image.png 3. 可变借用,这可以使用 inout 关键字

image.png

NonCopyable的deinit

NonCopyable的enum和struct可以声明deinit,deinit会在生命周期消失时调用

image.png

资料

medium.com/@reshmaUnni…