前言
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的
NonCopyable不能应用到下面的类型上
protocols
generic parameters
associated type requirements in protocols
the Self type in a protocol declaration, or in extensions
NonCopyable作为函数参数必须指明所有权的处理方式
和Rust中一样,在Swift中对所有权的处理的方式也有三种
- 所有权转移,这可以使用
consuming
关键字。在调用printVehicle时newVehicle的所有权就转移到了printVehicle 函数的vehicle参数上。后面在createVehicle中对newVehicle的属性修改会报错
但由于newVehicle我们使用var修饰,它是一个变量,因此它依然可以指向新的值。只是说继续使用原来的值是不可以的
- 不可变借用,这可以使用
borrowing
关键字。borrowing修饰后参数即是let,不可修改。createVehicle拥有newVehicl的所有权,而printVehicle只是临时借用了所有权
3. 可变借用,这可以使用
inout
关键字
NonCopyable的deinit
NonCopyable的enum和struct可以声明deinit,deinit会在生命周期消失时调用