6-18 内存管理
1.C语言中,一个malloc必须只能对应一个free
堆空间需要手动释放。
C语言当中,只要涉及堆空间的使用,就要考虑释放问题;我们可以提供一个计数器来解决堆空间释放问题。多一个人使用,计数器加1;减少一个人使用,计数器减1;当计数器为0时,释放堆空间。
********************************************************************************************
2.OC的内存管理
1)什么时候需要进行内存管理?
答:alloc的空间在堆空间;我们就需要进行手动释放。
------------------------------------------------------------------------------------
2)内存管理作用:
a.解决内存泄露
b.内存崩溃(不能多次释放,不能过早释放)
------------------------------------------------------------------------------------
另:Xcode操作:手动管理内存时,创建工程时,不要勾选 use automatic reference counting//为自动管理内存
------------------------------------------------------------------------------------
3)alloc & retain & release
例子:
--------------alloc 置1------------------
Dog * dog = [[Dog alloc]init];
//alloc的空间在堆空间;我们就需要进行手动释放
//alloc开辟一个对象的堆空间,然后把对象的地址赋给了dog对象指针;
-------------retain 加1------------------
//当多出一个指针指向这个对象堆空间,那么这个对象的计数器就要加1
Dog * dog1 = [dog retain];//计数器加1操作,然后把dog指向的对象地址赋给dog1
NSLog(@"retainCount = %lu",dog.retainCount);//显示对象的计数器的数值
注意:
Dog * dog1 = [dog retain];//规范写法
// [dog retain]; //写法不规范,尽量不要这样使用;容易造成少release一次。
------------release 减1------------------
[dog1 release];//使计数器减1
//当计数器为0时,会自动调用真正的释放函数dealloc;
[dog release];//dog指针使用完之后,要release
注意:
release一个对象指针后,就不可以再对这个对象指针进行操作了,这种操作是非法的,错误的。
------------------------------------------------------------------------------------
4)内存管理黄金法则 & 各人顾各人原则
-------黄金法则:
当我们通过alloc/retain/new/MutableCopy开头的函数,把对象地址给一个新的对象指针;然后这些新的指针用完之后,就应该立即release/autorelease;
-------其他知识点补充:
Dog * dog = [[Dog alloc]init]; //等价于Dog * dog = [Dog new];
黄金法则的应用:要注意什么时候retain 什么时候release
-------各人顾个人原则:
每个对象指针只需要管理自己的就可以,不需要管理别人。
不遵循各人顾个人原则的错误示例:
Dog * dog = [[Dog alloc]init];
Dog * dog1 = [dog retain];
[dog release];
[dog release]; //这样管理是错误的,没有遵循各人顾个人原则,这时dog1指针也无法使用了。
------------------------------------------------------------------------------------
5)关于字符串的内存管理
字符串是一个非常特殊的对象,有些字符串在堆空间,有些不在,(即使使用了alloc创建,可能也不在堆空间)即:有些需要内存管理,有些不需要管理,这时显得特别混乱,如何解决这个问题呢?
答:虽然有些不需要进行内存管理,但仍然按照堆空间进行内存管理的话,仍然不会影响程序。
只要保证一个alloc对应一个release;一个retain对应一个release就可以保证正确。
另:
字符串常量:
NSString * str = @"welcome to 1000phone!";//字符串常量,在只读数据段
//而内存管理管理的是堆空间
//所以不需要进行如下操作,来进行内存管理。
NSString * str1 = [str retain];
NSLog(@"count = %lu",str.retainCount);
------------------------------------------------------------------------------------
6)成员变量是对象指针的init函数 & setter函数 & dealloc函数的写法
以下三个例子的前提说明:有两个类:Car和Engine,Car类中包括一个成员变量:Engine * engine;
-----------init函数--------------
例子:
-(id)init
{
if (self = [super init])
{
engine = [[Engine alloc]init];
//当成员变量为一个对象指针时,无参的初始化函数这样写。
}
return self;
}
-----------手动实现setter函数-------------
例子:
//成员变量是对象指针
//一个对象如果没有赋初值,那么,所有成员变量初始值为0
//在这里,当创建一个car对象之后,engine这个成员变量初值为nil,而nil可以调用任意函数,(实际上没有做任何执行),因此,当第一次使用setEngine时,[engine release];即等价于:[nil release];这里执行没有任何问题。
-(void)setEngine:(Engine *)_engine
{
//setter函数的一个模板形式:
if (engine != _engine)
//旧值与新值不相等时才进行如下操作;否则的话1)如果连续两次赋相同的值,以下操作没有必要。2)赋值一次之后,release传入的值,若再传入,如果不进行判断,则会出现问题。
{
[engine release];//在赋新值之前,要把旧值release一次。
engine = [_engine retain];
}
}
-----------@propetry & @synthesize实现setter &getter函数-------------
例子:
@property (retain) Engine * engine;//等价于上面的手动实现setter函数
//默认属性是:atominc readwrite
//通过@synthesize对engine实现的getter函数retain了一次。而这次retain对应的释放,则交给了自动释放池.autorelease:自动释放/延迟释放/等一会再释放
------getter函数等价于下面的函数:
-(Engine *)engine
{
return [[engine retain]autorelease];
}
------------dealloc函数----------
例子:
-(void)dealloc
{//当成员变量为一个对象指针时,如果成员变量,出现了alloc/retain 要重写dealloc函数,成员变量在dealloc中,只能release一次。
//Car指向的对象消失之前,调用这个函数。
[engine release];//先把成员变量指向的对象的计数器减1
[super dealloc];//汽车整个对象(包含成员变量)最后再消失。
}
------------------------------------------------------------------------------------
7)自动释放池:autoreleasepool & 自动释放/延迟释放/等一会再释放:autorelease
----何时使用自动释放autorelease?
答:autorelease只有在不能用release的时候才去使用,否则的化,会造成内存泄露。
例子:
+(Dog *)creatDog
{
Dog * dog = [[Dog alloc]init];
return [dog autorelease];//这里不能使用release的,只能使用autorelease
//autorelease:把这个对象指针放入最近的自动释放池中,仅此而已;(计数器不会减1)
}
autorelease的执行过程:
答:autorelease:把这个对象指针放入最近的自动释放池中,仅此而已;(计数器不会减1)
-----autoreleasepool
本质:和OC数组一样
作用:自动释放池消失的时候会给每一个元素发送一个release消息。
作用域:新版本的autoreleasepool作用域在{}内;
------------------------------------------------------------------------------------
8)数组的内存管理
a.数组添加元素,不需要我们进行内存管理,因为没有手动调用alloc/retain这些函数;
b.数组release时,会给每一个元素发送一个release消息
c.[array addObject:dog];//会使dog的retainCount计数器加1;但不用我们手动释放,释放交给了自动释放池
d.牢记遵循黄金法则
例子:
Dog * dog = [[Dog alloc]init];
NSLog(@"dog count = %lu",dog.retainCount);
NSMutableArray * array = [[NSMutableArray alloc]init];//1
[array addObject:dog];//会使dog的retainCount计数器加1;但不用我们手动释放,释放交给了自动释放池//2
[array addObject:dog];//3
[array addObject:dog];//4
//数组添加元素,不需要我们进行内存管理,因为没有手动调用alloc/retain这些函数;
NSLog(@"dog count = %lu",dog.retainCount);//4
[dog release];
[array release];//数组release时,会给每一个元素发送一个release消息
NSArray * array1 = [NSArray arrayWithObject:@"one"];
//这个array1不需要release,我们要遵循黄金法则。
********************************************************************************************
本文详细介绍了Objective-C的内存管理,包括C语言中malloc与free的对应关系,OC内存管理的作用与重要性,以及手动管理内存时的alloc、retain、release操作。同时,讲解了内存管理的黄金法则和各人顾各人原则,并通过实例阐述了字符串、成员变量、自动释放池和数组的内存管理策略。
666

被折叠的 条评论
为什么被折叠?



