看到此篇文章,就当作你已经学习好了面向对象的基本。
(我认为这种理论概念的东西,没有任何一位老师一说就就会懂。
这里就不提我当年的老师多么NB,他说了几次我都没懂,可能是我笨。
大家还是自己领悟,主要还是多敲代码,这样更容易理解为什么要面向对象)
我们现在要介绍的是oc 关于内存的一系列介绍。
之前你也看到在第一片文章中。@autoreleasepool
这个东西是在Xcode4.2及之后的版本中由于引入的ARC(Automatic Reference Counting)机制。
跟java的GC功能相同。
但是是两码事,ARC是编译时编译器“帮你”插入了原本需要自己手写的内存管理代码,
而非像GC一样运行时的垃圾回收系统。而是程序编译时Xcode可以自动给你的代码添加内存释放代码。
但是在ObjC中没有垃圾回收机制,那么ObjC中内存又是如何管理的呢?
其实在ObjC中内存的管理是依赖对象引用计数器来进行的:
在ObjC中每个对象内部都有一个与之对应的整数(retainCount),
叫“引用计数器”,当一个对象在创建之后它的引用计数器为1,
当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1
(ObjC中调用一个对象的方法就是给这个对象发送一个消息),
当调用这个对象的release方法之后它的引用计数器减1,
如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。
所以 只要alloc init后 不用的对象一定要release 否则就会造成内存泄露。
而java的内存则适用一种比较复杂的内存释放机制。
简单介绍下java的内存,java任何一款虚拟机都没有同上面类似的清理方法。
java虚拟机的思路是一切获得对象都能追溯到期存活的堆栈或静态储存区,
遍历所有的引用就能找到所有活得对象。对发现的每一个引用必须追踪到它所引用的对象,
然后是此对象包含的所有引用,如此反复。直到根源堆栈和静态区形成的网络全部被访问到。
在这种方法下,有一种自适应的垃圾回收技术。如何找到存活对象取决于不同的虚拟机。
有一种发方法叫做停止-复制。它意味着先暂停程序(它不属于后台垃圾清理)然后将
他们全部拷贝到一块 新分离的堆内存中。之后删除原来的堆内存全部对象。
这样开始肯能效率比较慢(两个原因.1是要有两个堆 2是两个堆来回折腾),当程序慢慢稳定后。
会转换成 标记-清理
“标记-清扫”所依据的思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。
每当它找到一个存活对象,就会给对象设一个标记,这个过程中不会回收任何对象。
只有全部标记工作完成的时候,清理动作才会开始。
在清理过程中,没有标记的对象将被释放,不会发生任何复制动作。
所以剩下的堆空间是不连续的,垃圾回收器要是希望得到连续空间的话,就得重新整理剩下的对象。
想想java的内存管理机制就够高端、省心。
这里我们既然了解了oc 和java 的内存回收机制,就不得不探讨下这个对象初始化分配内存的内容了。
初始化关键词:new 和
alloc init
在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init]
这是为什么呢?
不知大家发现了没有:如果使用new的话,初始化方法被固定死只能调用init.不能调用我们准备好的别的初始化方法
这样是十分不灵活的。
但是除了这种默认初始化外还有别的不同么。答案是当然有
借助源码我们详细看看他们的区别
+ new
{
id newObject = (*_alloc)((Class)self, 0);
Class metaClass = self->isa;
if (class_getVersion(metaClass) > 1)
return [newObject init];
else
return newObject;
}
//而 alloc/init 像这样:
+ alloc
{
return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
- init
{
return self;
}
区别只在于alloc分配内存的时候使用了zone.
这个zone是个什么东东呢?
它是给对象分配内存的时候,
把关联的对象分配到一个相邻的内存区域内,
以便于调用时消耗很少的代价,提升了程序处理速度;