我们在之前的章节中提到过,Swift中的类型分为值类型和引用类型。前者是在赋值时进行复制,而后者则是传递了一个引用给等号左边的那个变量。究其原因,就是两种类型在内存分配和管理时的差异。
值类型(Swift的基础类型,开发者自定义的枚举和结构体)的内存分配逻辑很简单。当开发者创建一个值类型实例时,编译器会根据其类型和内部属性的情况去向系统申请相应大小的内存。而当值类型的实例被赋值给其他变量或传入函数时,编译器会在这个过程中创建这个实例的一份拷贝,这份拷贝是一份完全的拷贝,其每个属性也都会被拷贝一份。当这个实例不再使用时,Swift会将其内存回收,而开发者无须关心值类型的内存管理。
引用类型(Swift中提供的类,以及开发者自定义的类)的内存分配逻辑则相对复杂一些。在创建一个类的实例时,系统会为实例分配内存,跟值类型的方式一样。但是在赋值和传入函数时,两者有很大的区别:编译器并不会为这个实例创建一份拷贝,而是创建一个新的引用,指向同一块内存区域,在函数中或是其他变量对这块引用的内存区域进行修改,其他引用的地方都能看到这些修改后的变化。这就是引用类型和值类型在内存分配上最大的差别。(www.xing528.com)
由于引用类型是通过这样的方式去分配内存,所以编译器帮开发者维护了一个引用计数(reference count),这个数代表了每个实例被多少其他的变量或者函数所引用着。只要这个数字大于零,这个实例就不会被释放;一旦这个引用计数变为零,那么在一个周期内,这个实例就会被释放,并且执行其deinit方法。
在早期的iOS系统中,使用的是MRC(Manual Reference Count)手动引用计数,需要开发者大量编写retain和release的代码,使得编译器知道何时应该给实例的引用计数加一,何时应该给实例的引用计数减一。在2011年,苹果为Objective-C引入了ARC(Automatic Reference Count)自动引用计数,从此开发者就不再需要编写大量的retain和release的代码来进行实例的内存管理了。因为Swift本身已经建立在了ARC的基础之上,所以开发者不需要在代码中增加retain和release的操作。但是开发者仍然需要了解ARC的一些机制,这样可以避免犯一些内存管理上的错误,从而减少应用因占用内存过大而被系统强制退出的情况。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。