码迷,mamicode.com
首页 > 其他好文 > 详细

Objective-C_内存管理

时间:2015-09-17 21:29:28      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

内存管理

MRC:

对象的生命周期:

1.通过alloc,new和copy等方式将对象产生出来,这个时期是对象的产生时期

2.初始化后的对象可以接收消息和执行动作,也可以和其它对象进行信息交换和相互调用,这个时期是对象的生存时期

3.对象完成其使命后,我们将其从内存中移除,这个时期是对象的死亡和销毁时期

引用计数器:

1.当对象刚刚被创建其初始值为1

2.当有某段代码需要访问一个对象时,会将该对象的引用计数器加1(通过retain来实现)

3.当某段代码结束访问一个对象时,会将该对象的引用计数器减1(通过release来实现)

4.当某段代码结束访问一个对象时,如果采用了autorelease方式,在当前自动释放池结尾会将该对象引用计数器减1

5.当对象的引用计数器为0时,代表所有其它代码均不再需要访问该对象,该对象会被自动销毁,其占用的内存空间会被回收

示例:

#import <Foundation/Foundation.h>

#import "Student.h"

#import "Dog.h"

int main(int argc, const char * argv[]) {

    @autoreleasepool {

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

        NSLog(@"dog.retainCount:%ld",dog.retainCount);//为1

        [dog release];

   NSLog(@"dog.retainCount:%ld",dog.retainCount);

        [dog bark];

        //注意:写完之后多运行几次,看看会造成什么效果,dog虽然是release了,但是偶尔还能调用dog的方法,这是因为编译器有时候跑得很快,还没来得及释放,就已经跑完所有代码了,事实上dog已经释放了  

    }

    return 0;

}

运行结果:

2015-09-17 16:39:37.633 OC_5.0_MemeryManage[853:43528] dog.retainCount:1

2015-09-17 16:39:37.635 OC_5.0_MemeryManage[853:43528] dog 已经被释放了

2015-09-17 16:39:37.635 OC_5.0_MemeryManage[853:43528] dog.retainCount:1

2015-09-17 16:39:37.635 OC_5.0_MemeryManage[853:43528] 汪汪汪汪。。。。

上面的例子,第二次retainCount,按原理应该为0,但却不是。苹果公司的文档关于此问题的解释是:在调试程序的时候观察对象的retainCount值是没有意义的,因为系统框架中的对象可能还会retain该对象以便保持对其引用,同时自动释放池也可能会持有该对象,因此不能仅凭retainCount来判断对象的引用计数。所以说retainCount只是一个参考值

对象所有权

内存管理模型是基于对象所有权的。一个对象可能有一个或多个所有者。只要对象有走过一个所有者,则该对象会一直存在。

为了要搞清什么时候拥有对象,什么时候不再拥有,有如下的原则

1.谁创建谁拥有,可以通过alloc,new,copy,mutableCopy等方法创建的对象

2.可以通过retain来获取对象的所有权

有两种情况需要使用retain:(1)在setter方法和init方法里,当你想要将一个对象作为属性来使用

             (2)为了避免其它操作使对象变成无效的对象

3.如果不再需要一个对象,必须释放拥有对象的所有权

4.如果不拥有一个对象,不能释放该对象的所有权

集合与对象所有权

当我们将一个对象加入到集合(如数组、字典、set集合)中时,集合会拥有该对象的所有权;当集合移除该对象,或者集合对象本身被清理,集合会放弃对象的所有权。

为了确保内存管理不出错,总结了以下几点原则

1.当使用new,alloc或copy方法创建一个对象时,该对象引用计数器为1.如果不需要使用该对象,可以使用release或autorelease方法,在其使用完毕将其销毁

2.如果通过其他方法获取一个对象,则可以假设这个对象,引用计数为1,并且被设置为autorelease,不需要对该对象进行清理,如果确实需要retain这个对象,则需要使用完毕后release

3.如果retain了某个对象,需要release或autorelease该对象,保持retain和release使用次数相等

总得来说就是,谁创建 ,谁释放。

在dealloc中释放对象的所有权

在使用dealloc中要注意:

1.绝对不要直接调用另一个对象的dealloc方法

2.在dealloc方法实现的最后要调用父类的dealloc方法

3.当应用结束时,系统未必会调用对象的dealloc方法

采用弱引用避免循环retain 

 例子:

教师类中有学生

#import <Foundation/Foundation.h>

@class Student;

@interface Teacher : NSObject

@property(nonatomic,retain)Student *student;

@end

 

学生类中有教师

#import <Foundation/Foundation.h>

@class Teacher;

@interface Student : NSObject

@property(nonatomic,retain)Teacher *teacher;

@end

相互retain强强引用,就会造成,你中有我,我中有你,要释放student,那么就要释放teacher,要释放teacher,那么就要释放student

 大家都在等待对方释放,循环retain

解决办法就是其中一个使用弱引用assign;

ARC

ARC技术实际也是运用引用计数,只是程序员不用再去手动引用计数,相当于身边多了一个内存管理高手帮助我们去管理内存 

ARC技术引入了一些新的规则:

1.不能显式调用,dealloc语句,或实现或者调用retain,release,retainCount和autorelease等方法

2.不能调用@selector(retain)、@selector(release)等等

3.可以实现dealloc,但方法中不用释放实例变量,也不能调用[super dealloc].

4.不能使用NSAutoreleasePool对象,用@autorelesepool块来代替

5.不能用开头为new的名称来定义一个属性,除非定义一个别的getter名称,如下:

//以下代码不能正常工作:

@property NSString *newTitle;

//这样可以

@property (getter = theNewTitle) NSString *newTitle;

 

浅拷贝与深拷贝

copy:

1.copy对于不可变对象相当于retain,

2.对于可变对象,是深拷贝(复制了一个新的内存空间,新对象与旧对象不是同一个)

3.但是深拷贝不一定是完全拷贝。对象里面复合的对象有可能还是浅拷贝,甚至是没有拷贝

mutableCopy:

不可变对象经过mutableCopy之后,发生了深拷贝,而且返回一个可变对象

Objective-C_内存管理

标签:

原文地址:http://www.cnblogs.com/Jimmy-Home/p/4816948.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!