OC基础 内存管理
我们所了解的c语言内存管理,如下:
(1)c语言的内存分配:char *p = (char*)malloc(100*sizeof(char));
(2)c语言的内存释放:free(p);
c语言内存管理存在的缺陷:
(1)不释放就会造成内存泄露。
(2)多次释放就会造成崩溃。
(3)大型项目中多人对一块内存进行操作时,不能释放内存,因为不知道别人是否还在使用。
oc语言的内存管理
1.内存管理
(1)引用计数。
(2)内存管理的黄金法则:谁创建谁释放。
让我们来看一下测试例子:
#import <Foundation/Foundation.h> #import "Student.h" int main(int argc, const char * argv[]) { @autoreleasepool { //内存管理 //用引用计数来管理: //alloc/retain/copy 引用计数加1 //release引用计数减1 //只有使用过alloc/retain/copy,才能调用release //内存管理的黄金法则--谁创建谁释放 Student *stu = [[Student alloc] init]; [stu retain]; [stu retain]; NSLog(@"%ld",[stu retainCount]); Student *stu4 = [stu copy]; NSLog(@"%ld",[stu retainCount]); NSLog(@"%ld",[stu4 retainCount]); NSLog(@"%p",stu); NSLog(@"%p",stu4); } return 0; }
测试结果:
2.类的复合中使用setter
Student类,Student.h文件:
#import <Foundation/Foundation.h> @interface Student : NSObject @end
Student.m文件:
#import "Student.h" @implementation Student -(NSString *)description { return @"我是学生"; } @end
Teacher类,Teacher.h文件:
#import <Foundation/Foundation.h> #import "Student.h" @interface Teacher : NSObject { Student *_stu; } -(void)setStu:(Student *)stu; -(Student *)getStu; -(void)printf; @end
Teacher.m文件:
#import "Teacher.h" @implementation Teacher //错误方法1: //因为stu对象释放掉时,teacher内的_stu就指向了一个未知地址,不再指向原来的stu,所以stu需要retain,得到错误方法2 //-(void)setStu:(Student *)stu //{ // _stu = stu; //} //错误方法2: //因为用另外一个stu2对象赋值的时候,原先的_stu指向的stu1内存地址不会被释放,造成内存泄漏.所以在retain之前需要先释放掉旧的地址空间,得到错误方法3 //-(void)setStu:(Student *)stu //{ // _stu = [stu retain]; //} //错误方法3: //假如调用setStu传入的对象指针是同一个对象,那么[_stu release]之后,stu指向的内存地址的引用计数已经变为0,内存被释放,无法再retain,所以得到正确的方法4 //-(void)setStu:(Student *)stu //{ // [_stu release]; // _stu = [stu retain]; //} //正确的方法4 //release和retain都要放在if的语句块内,否则也会造成内存泄漏 -(void)setStu:(Student *)stu { if(_stu != stu) { [_stu release]; _stu = [stu retain]; } } -(Student *)getStu { return _stu; } -(void)printf { NSLog(@"%@",_stu); } @end
3.数组的内存管理
数组的内存管理,同样使用内存的黄金法则:
(1)当我们创建数组的时候,数组会对每个对象进行引用计数加1。
(2)当我们把数组销毁的时候,数组会对每个对象引用计数减1。
(3)当我们给数组添加对象的时候,会对对象进行引用计数加1。
(4)当我们给数组删除对象的时候,会对对象进行引用计数减1。
总而言之,谁创建谁释放,遵守内存的黄金法则。
测试例子:
#import <Foundation/Foundation.h> #import "Student.h" int main(int argc, const char * argv[]) { @autoreleasepool { //数组创建时:对象指针指向的内存地址引用计数加1 //数组读取对象时:引用计数不变。 Student *stu1 = [[Student alloc] init]; Student *stu2 = [[Student alloc] init]; NSArray *array = [[NSArray alloc] initWithObjects:stu1,stu2, nil]; Student *stu3 = [array objectAtIndex:0]; NSLog(@"%ld",[stu1 retainCount]); NSLog(@"%ld",[stu3 retainCount]); NSLog(@"%p",stu1); NSLog(@"%p",stu3); } return 0; }
测试结果:
4.自动释放
(1)系统自动释放池:在runloop循环时,系统判断系统自动释放池内的对象的引用计数,如果为1并且持有对象-1时,就释放对象,不为1时,如果持有对象-1,引用计数就-1,否则引用计数不变。
(2)自定义的自动释放池,当自动释放池结束时,释放自动释放池内的对象。