OC-内存管理

本文详细介绍了Objective-C的内存管理,包括C语言中malloc与free的对应关系,OC内存管理的作用与重要性,以及手动管理内存时的alloc、retain、release操作。同时,讲解了内存管理的黄金法则和各人顾各人原则,并通过实例阐述了字符串、成员变量、自动释放池和数组的内存管理策略。

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

//通过@synthesizeengine实现的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];//会使dogretainCount计数器加1;但不用我们手动释放,释放交给了自动释放池

d.牢记遵循黄金法则



例子:

Dog * dog = [[Dog alloc]init];

NSLog(@"dog count = %lu",dog.retainCount);

        

NSMutableArray * array = [[NSMutableArray alloc]init];//1

[array addObject:dog];//会使dogretainCount计数器加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,我们要遵循黄金法则。

********************************************************************************************













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值