内存管理 ARC + MRC

来源:互联网 发布:身知内功 编辑:程序博客网 时间:2024/05/02 00:28

C语言内存管理

     char *p = malloc(100);   //在堆中开辟100个字节空间        strcpy(p,"hello");        NSLog(@"p = %s",p);        fun1(p);        fun2(p);//C内存管理的隐患:        //free(p);  //1.当fun1,fun2没用完malloc空间,执行了free,造成提前释放--野指针        //2.担心传出去的空间,别人没用完,所有人都不去释放--内存泄漏        free(p); //3.所有人都担心内存没释放,都执行free,造成重复释放 -- 奔溃//OC中改善内存管理的机制--引用计数        //引用计数: ARC 、MRC        //ARC:  自动引用计数-(默认)        //MRC:  手动引用计数## 标题 ##

ARC

int main(int argc, const char * argv[]) {    @autoreleasepool { //自动释放池        // insert code here...        //ARC执行过程:        //先执行@autoreleasepool括号内->dealloc->自动释放池括号外        Person *per = [[Person alloc] init];        NSLog(@"开辟空间");    }    NSLog(@"程序即将结束");    return 0;    }//析构方法:释放内存的方法;程序执行完毕,进入dealloc,说明已经释放该对象    - (void)dealloc    {        NSLog(@"Person dealloc");    }

MRC

int main(int argc, const char * argv[]) {    @autoreleasepool {        // insert code here...        //MRC执行过程:        //release:只要对象的引用计数为0->立即dealloc(不会等到自动释放池结束)(推荐)        //autoRelease: 把引用计数-1抛给自动释放池,退出自动释放池立即执行dealloc        Person *per = [[Person alloc] init];        NSLog(@"开辟空间");        [per release];  //引用计数-1;  减到0时,才释放(调用dealloc)        //[per autorelease]; //有延迟的引用计数-1;        NSLog(@"空间-1");    }    NSLog(@"应用程序执行结束");    return 0;    }

MRC的Retain调用

int main(int argc, const char * argv[]) {    @autoreleasepool {        // insert code here...        Person *xiaoM = [[Person alloc] init];        Person *xiaoQ = [xiaoM retain];  //引用计数+1        Person *xiaoB = [xiaoQ retain];        NSLog(@"引用计数:%ld",[xiaoQ retainCount]);  //获取引用计数        [xiaoM release];   //引用计数-1,计数还剩1        NSLog(@"-1后,引用计数:%ld",[xiaoM retainCount]);  //获取引用计数        //[xiaoM release]; err 一定要使用内存管理黄金法则        [xiaoQ release];        [xiaoB release];        //释放的值,再打印无意义        //NSLog(@"retainCount = %ld",[xiaoB retainCount]);        //结论: 只要有alloc、retain、copy,就一定对应有release-内存管理黄金法则    }    return 0;}

字符串的内存管理

    NSString *str = [[NSString alloc] init];        //在字符串中不能用retainCount来获取引用计数        NSLog(@"retainCount = %ld",[str retainCount]);   //-1//1.NSString进行retain        NSString *str1 = [str retain];  //引用计数+1        //字符串通过打印地址的方式,验证引用计数是否+1        NSLog(@"str1:%p,str: %p",str1,str);        [str release];  //内部遵循内存管理的黄金法则        [str1 release];        NSMutableString *mutStr = [[NSMutableString alloc] init];//2.NSMuatableString进行retain        NSMutableString *mutStr1 = [mutStr retain]; //引用计数+1        NSLog(@"mutStr:%p,mutStr1:%p",mutStr,mutStr1);        //结论:可变与不可变字符串进行retain,引用计数都+1;//3.NSString进行copy        NSString *str2 = [str copy];   //引用计数+1        NSLog(@"str: %p,str2: %p",str,str2);//4.NSMuatableString进行copy        NSString *str3 = [mutStr1 copy]; //引用计数不+1        NSLog(@"str3 = %p,mutstr1=%p",str3,mutStr1);        //结论:不可变进行copy引用计数+1,可变不+1;//5.NSString进行mutableCopy        NSMutableString *mutStr2=[str3 mutableCopy]; //引用计数不+1        NSLog(@"mutStr2=%p,str3 = %p",mutStr2,str3);//6.NSMutableString进行mutableCopy        NSMutableString *mutStr3 = [mutStr2 mutableCopy];//引用计数不+1        NSLog(@"mutstr3=%p,mutStr2=%p",mutStr3,mutStr2);        //结论:可变与不可变字符串进行mutableCopy,引用计数都不+1;//        //深拷贝:引用计数不+1、字符串的mutableCopy始终为深拷贝        //浅拷贝:引用计数+1、字符串的retain始终为浅拷贝

数组的内存管理

    Person *p1 = [[Person alloc] init];        Person *p2 = [[Person alloc] init];        Person *p3 = [[Person alloc] init];//1. 当元素对象放入数组,每一个对象的引用计数都+1        NSMutableArray *mutArr = [[NSMutableArray alloc] initWithObjects:p1,p2,p3, nil];        NSLog(@"p1 count = %ld",p1.retainCount);  //2        NSLog(@"p2 count = %ld",p2.retainCount);  //2        NSLog(@"p3 count = %ld",p3.retainCount);  //2//2.在数组中添加一个对象,那么该对象的引用计数+1        [mutArr addObject:p1];        NSLog(@"p1 count = %ld",p1.retainCount);  //3        NSLog(@"p2 count = %ld",p2.retainCount);  //2        NSLog(@"p3 count = %ld",p3.retainCount);  //2//3.数组中移除一个对象,那么该对象的引用计数-1        [mutArr removeObject:p3];        NSLog(@"p1 count = %ld",p1.retainCount);  //3        NSLog(@"p2 count = %ld",p2.retainCount);  //2        NSLog(@"p3 count = %ld",p3.retainCount);  //1//4.数组中溢出所有对象,那么每一个对象的引用计数都-1        [mutArr removeAllObjects];        //[mutArr release];        NSLog(@"p1 count = %ld",p1.retainCount);  //1        NSLog(@"p2 count = %ld",p2.retainCount);  //1        NSLog(@"p3 count = %ld",p3.retainCount);  //1        [p1 release];  //引用计数为0,调用dealloc        [p2 release];  //引用计数为0,调用dealloc        [p3 release];  //引用计数为0,调用dealloc

总结

     //1.回顾C内存管理的缺陷           //a. 提前释放  b. 重复释放  c. 没有释放        //2.引用计数的概念:           //a. ARC: 自动引用计数,退出自动释放池,系统自动会释放内存空间           //b. MRC: 手动引用计数;                //b1. 内存管理的黄金法则;                //b2. MRC默认的调用方法及标准写法                //调用方法:retain、retainCount、release、dealloc                //标准写法:记住复合类内存管理,字符串在类中的内存管理        //3. 字符串的内存管理                //深拷贝与浅拷贝的概念        //4. 数组的内存管理                //记住4个结论        //5.release与autorelease            //release: 引用计数-1(MRC推荐使用)            //autorelease: 有延时的引用计数-1

test

main:

int main(int argc, const char * argv[]) {    @autoreleasepool {        // insert code here...        //创建对象        Engine *eng = [[Engine alloc] init];        Engine *eng2 = [[Engine alloc] init];        Car *car1 = [[Car alloc] initWithEngine:eng];        [car1 setEngine:eng2];        //释放对象        [eng2 release];        [eng release];        [car1 release];    }    return 0;    }car:    @implementation Car    //setter函数    -(void)setEngine:(Engine *)engine    {    if (_engine != engine) {        [_engine release];        _engine = [engine retain];    }    }    //getter函数    -(Engine *)engine    {    return _engine;    }    //Car对象初始化    -(id)initWithEngine:(Engine *)engine    {    self = [super init];    if (self) {     // _engine = [engine retain];        _engine = engine;        [engine retain];    }    return self;    }    //重写dealloc    - (void)dealloc    {        [_engine release];        NSLog(@"%@ was dealloc!",self);        [super dealloc];    }    @endEngine:    @implementation Engine    //重写dealloc    - (void)dealloc    {        NSLog(@"%@ was dealloc!",self);        [super dealloc];    }    @end
1 0