首页 » Swift » 第三篇:Swift中的内存管理

第三篇:Swift中的内存管理

原文 http://blog.csdn.net/Xoxo_x/article/details/78910979

2017-12-28 02:01:21阅读(285)

1.好多人问我Swift内存管理是怎样的,当你也想问这样类似的问题或困惑时时,你可以参考本文。也从内存的角度上解释为什么会出现循环引用!

2.你需要了解Swift 、知道[weak self] 以及 [unowned self] 是什么?(提示:与循环引用有关 ),你最好明白这个否则会很疑惑我下面所说的。

首先我们要明白几件事:

值类型与引用类型 栈(stack)与堆(heap) 循环引用导致内存泄露 如何解决内存泄露

1.ARC与内存管理有什么关系?

ARC是内存管理的一种,还有MRC和自动释放池,在Swift中不支持MRC,而且MRC也不如ARC管理的好;无论是ARC还是MRC都是对引用类型的引用计数进行管理,如果引用计数为0,则由系统自动释放对象,MRC和ARC的最主要区别就是是否人为控制引用计数;所以了解ARC也就是了解了iOS的内存管理。

2.引用类型与ARC的关系?

ARC 名为自动引用计数,只有引用类型,才有引用计数
引用类型储存在内存当中的堆区(heap),创建引用对象时,引用计数自动加一,当不需要该对象时引用计数减一,引用对象类型就是多个对象指向一个地址,有多少个对象只想这个地址,那么引用计数就是几。

3.在swift中引用类型有哪些?

引用类型:class closure 即:类和闭包

4.值类型呢?内存管理不需要考虑值类型吗?

值类型储存在栈(stack)中,由系统自动分配,并不需要程序猿释放内存,同时在函数执行完毕后这些空间都将要被释放

5.常见的循环引用

1.引用类型总是被分配到“堆”上。
2.值类型总是分配到它声明的地方:
   a.作为引用类型的成员变量分配到“堆”上
   b.作为方法的局部变量时分配到“栈”上

线程开始执行函数,函数参数被压入线程堆栈。
引用类型,它被分配在“堆”上,并且由一个位于“栈”上的指针引用。
函数执行完毕后,“栈”同样会被清空,此时堆上存留保存引用类型的内存,也就是垃圾,我们需要手动释放掉,苹果为了不用人为控制内存释放,也并非用GC机制来处理,于是乎判断引用计数是否为零,如果为零就释放掉内存,如果是手动释放的就叫MRC,自动释放的就叫ARC。

如果,两个引用类型之间相互引用,引用指针由于是引用类型的成员变量,所以他会被分配在堆中,当清空栈的时候,此时推上还有两个相互引用的内存,我们需要释放掉这块内存,堆上的指针相互引用,导致ARC没有办法释放掉内存,

1). 两个类互相持有对方,导致系统没有办法释放内存。
2). 类中有闭包,导致内存泄露

6.swift中解决循环引用

[weak self] self?/. [weak weakSelf = self] weakSelf?. [unowned self] self.

weak与 unowned 的作用 ,weak是一个弱引用,当释放一个对象时,他并不会阻挠,从而破坏循环引用,unowned 是不持有引用,也就是不持有self 从而破坏循环引用。

7.关于GC机制与ARC的区别?

推荐文章 http://zhang.hu/arc-vs-gc/

 - 引用计数 (ARC,Automatic Reference Counting)
 - GC (Garbage Collection)
因为 Java 的流行,GC 被广泛的认知。GC 简单的说是定期查找不再使用的对象,释放对象占用的内存。
基于 GC,申请的对象不需要手动释放,只需要确认对象在不再需要时,不再被其他对象引用。
引用计数早期主要用于底层系统,比如文件系统的 inode 管理,后来 C++ 的 boost 库实现了一套完整的 ARC,目前流行的系统还有 Objective C 也是采用的 ARC。
ARC 的特点是,一个对象被引用时,引用计数增加 1,引用对象释放时,引用计数减少 1,如果引用计数为 0,释放对象。

这个时候你可能想知道堆和栈的具体差异:
参考这篇文章:http://blog.csdn.net/changyourmind/article/details/51816768
c++语言的,但原理是一样的。

堆和栈的主要区别由以下几点:
  1、管理方式不同;
  2、空间大小不同;
  3、能否产生碎片不同;
  4、生长方向不同;
  5、分配方式不同;
  6、分配效率不同;
(1)管理方式
对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生内存泄露。
(2)空间大小:
一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看 堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M。当然,这个值可以修改。
(3)碎片问题
对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构。
(4)生长方向
对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
(5)分配方式
堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的, 比如局部变量的分配。动态分配由malloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
(6)分配效率
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

8.关于深拷贝与浅拷贝

浅拷贝:拷贝指针
深拷贝:拷贝指针和地址
值类型的赋值操作是深拷贝,引用类型的赋值操作是浅拷贝

最新发布

CentOS专题

关于本站

5ibc.net旗下博客站精品博文小部分原创、大部分从互联网收集整理。尊重作者版权、传播精品博文,让更多编程爱好者知晓!

小提示

按 Ctrl+D 键,
把本文加入收藏夹