黑马程序员——OC语言日志——内存管理的原理、分类和原则

来源:互联网 发布:对网络教育的评价 编辑:程序博客网 时间:2024/05/19 10:40

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1、内存管理的原理

1)对象所有权及引用计数器
对象所有权:任何对象都可能拥有一个或者多个所有者,只要一个对象至少拥有一个所有者,它就会继续存在。
Coaoa所有权策略:任何自己创建的对象都归自己所有,可以使用名字以“alloc”或者“new”开头或名字宏包含copy的方法创建对象,可以使用retain来获取一个对象的所有权。
对象的引用计数器:每个OC对象都有自己的引用计数器,是一个整数表示对象被引用的次数,即现在有多少定西在使用这个对象,对象刚刚被创建时。默认计数器值为1,当计数器的值变为0时,则对象先销毁。
每个OC对象内部都专门有8个字节的存储空间来存储引用计数器。
3)引用计数器的作用

引用计数器是判断对象要不要被回收的依据(存在一种例外,对象值为nil,引用计数器为0,但不回收空间)就是计数器是否为0,若不为0 则存在。
4)引用计数器的操作

给对象发送小时,进行相应的计数器操作
retain消息:是计数器+1,该方法返回值本身
release消息:使计数器-1(并不代表释放对象)
retaincount消息:获得对象当前的引用计数 %ld %tu
5)对象的销毁
当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收。

当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的“临终遗言”。
一旦重写了dealloc方法就必须调用[super dealloc],并且在代码块的最后调用(不能直接调用dealloc方法)
一旦对象被回收了,那么它所占据的存储空间就不在可用,坚持使用会导致程序崩溃(野指针错误)。
6)注意:
(1)如果对象的计数器不为0,那么在整个程序运行过程中,它占用的内存就不可能被回收(除非整个程序已经退出)
(2)任何一个对象,当剩下来的时候,引用计数器的值都为1,(对象一旦创建好,默认引用计数器就是1)当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1.
2、OC内存管理分类
objective-C提供了三种内训管理方式:
ManulReference Counting(MRC,手动管理,在开发 ios4.1之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain、autorelease、autorelease 等,而在其后的版本可以使用ARC ,让系统自己管理内存。)
    automatic reference counting (ARC,自动引用计数,ios4.1之后推出的)
    garbage collection (垃圾回收)。ios不支持垃圾回收。
    ARC作为苹果新提供的技术,苹果推荐开发者使用ARC技术来管理内存。

将ARC调为MRC的方法:将项目那一项的YES改为NO,如图


3、代码实现手动内存管理

#import <Foundation/Foundation.h>#import "Person.h"int main(int argc, const char * argv[]) {    @autoreleasepool {        Person *p = [Person new];//对象有一个所有者        //证明有一个所有者        NSUInteger count = [p retainCount];        NSLog(@"%lu",count);        //使用引用计数器+1        Person *p2 = [p retain];//引用计数器+1        NSLog(@"p2.retainCount=%lu",[p retainCount]);        //如果回收对象,”该retainCount=0        [p release];//retainCount-1=1        NSLog(@"p.retainCount=%lu",[p retainCount]);        [p release];//retainCount-1=0        //p已经被回收,不能再‘用p对象        //NSLog(@"p.retainCount=%lu",[p retainCount]);        //证明p的空间被释放,重写dealloc方法                    }    return 0;}
在Personk类的实现中,重写dealloc方法:

#import "Person.h"@implementation Person//dealloc方法为对象临终遗言,对‘被销毁时,会默认调用该方法//该方法时系统根据引用计数器的值自动调用-(void)dealloc{    NSLog(@"Person已经被回收!");    //释放父类    [super dealloc];}@end
打印:2015-10-26 22:48:11.463 手动内存管理的快速入门[684:303] 1
2015-10-26 22:48:11.476 手动内存管理的快速入门[684:303] p2.retainCount=2
2015-10-26 22:48:11.482 手动内存管理的快速入门[684:303] p.retainCount=1
2015-10-26 22:48:11.486 手动内存管理的快速入门[684:303] Person已经被回收!
4、内存管理的原则

1)原则
只要还有人使用某个对象,那么这个对象就不能被回收;
只要你想使用这个对象,那么久应该让这个对象的引用计数器+1;
当你不想使用这个对象时,应该让对象的引用计数器-1;
2)谁创建,谁realse
(1)如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法
(2)不是你创建的就不用你去负责
3)谁retain谁release
只要你调用了retain,无论这个对象是如何生成的,你都要调用release
4)总结
有始有终,有加就用过有减,曾经让某个对象计数器加1,就应该让其在最后减1

5、内存管理研究的内容
1)野指针:1、定义的对象没有被初始化

                       2、指定的空间已经被释放
2)内存泄露:
Person *p = [Person new]//P在栈区 ,[Person new]在堆区
如果
{
Person *p = [Person new];
}//这段代码执行完,p在栈区被释放
//而[Person new]在堆区没有被释放,就是内存泄露


0 0