首页 > 其他 > 详细

7.内存管理

时间:2016-02-17 20:59:44      阅读:182      评论:0      收藏:0      [点我收藏+]
内存问题体现:内存溢出和野指针
内存管理方式:垃圾回收机制、MRC、ARC
垃圾回收机制:程序员只需开辟内存空间,不需要用代码的形式释放,系统会判断不被使用的空间,然后回收。
MRC:人工引用计数,内存的开辟和释放都是由程序代码进行控制。
ARC:自动引用计数,只允许用户开辟空间,不用释放空间,垃圾回收机制的本质就是ARC

iOS支持两种内存管理方式:ARC和MRC
MRC的内存管理机制是:引用计数
ARC是基于MRC的

OC采用引用计数机制管理内存,每个对象都有一个引用计数器,用来记录当前对象的引用的引用次数,OC对象内部,都专门有4个字节的存储空间来存储引用计数器。
retainCount 获取对象的引用计数,占位符%lu

引用计数的理念:通过控制内存或者对象的引用来实现生成、持有、释放、销毁
生成对象:+alloc    开辟内存空间,让被开辟的内存空间的引用计数从0变为1
持有对象:-retain    引用计数加1
释放对象:-release   引用计数立即减1
                    -autorelease   未来的某一时刻引用计数减1和autoreleasepool自动释放池有关
销毁对象:-dealloc     当对象的引用计数为0时,系统就会回收这个内存空间

引用计数这个概念只在堆区域,针对堆区的对象

生成对象:方法+(instancetype)alloc;在堆区域开辟一块内存空间,存放对象,并且将内存清零。并且将引用计数变为1,这是从0到1的过程
Person *person = [[Person alloc] init];//person的引用计数从0变为1
持有对象:方法retain,让对象的引用计数加1
[person retain];


释放对象:方法release,让对象的引用计数立即减1
person对象初始化alloc之后,引用对象加1,retain引用计数加1,所以要释放2次,执行两次release操作
[person release];-1
[person release];-1
NSLog(@"%lu",[person retainCount]);
此时打印引用计数的次数,打印出来为1。此行代码本身错误,person对象已经被释放了,如果在去访问[person retainCount]会造成野指针!

注:引用计数没有0的概念,当对象的引用计数为1时,在做release操作之后,系统为自动执行dealloc方法,释放对象,来完成对象的内存管理。

为了证明person对象已被释放,在person对象中重写dealloc方法
只要重写了dealloc方法,[super dealloc];永远在最后执行
先将自身的实例变量释放,然后在执行父类中的dealloc方法,释放继承过来的实例变量。
dealloc方法正好与初始化方法顺序相反


autorelease 此方法也是让对象的引用计数减1,但不是立即减1
自动释放池(autorelease pool)是OC的一种内存自动回收机制,控制autorelease对象的释放,可以将一些临时变量通过自动释放池来回收统一释放,自动释放池在本身销毁的时候,池子内的所有对象都会做一次release操作

创建自动释放池

自动释放池释放的时候,遵循先进后出,先进入的后释放。


内存管理原则:
1、在一段代码内,增加和减少的次数要相等,使用了alloc、retain、copy让内存的引用计数增加的,就需要使用release或者autorelease让内存的引用计数减少。
2、增加次数大于减少次数,会造成内存泄漏
3、增加次数小于减少次数,会造成过度释放
4、增加次数等于减少次数,还继续访问,就会造成野指针


协议是一堆方法的声明,只有.h文件,定义协议的关键字@protocol @end
协议中的方法默认是必须实现的,即@required。关键字@optioal 修饰的方法是可选的,可实现也可以不实现。


遵循协议:
引入协议头文件,加入协议

copy方法
一个对象想要copy,生成自己的副本,需要服从NSCopying协议,定义cop的细节
NSCopying协议的方法:
技术分享
根据copyWithZone:方法的实现不同,拷贝分为:伪拷贝、浅拷贝、深拷贝

伪拷贝:相当于没有,相当于让外界对象执行一次retain操作,引用计数加1
- (id)copyWithZone:(NSZone *)zone { //NSZone 预留空间
    return [self retain];
}


浅拷贝:对象开辟新的空间,但是两个对象的实例变量指向同一个内容。
- (id)copyWithZone:(NSZone *)zone {
    Person *person = [[Person allocWithZone:zone]init];
    person.name = self.name;
    person.gender = self.gender;
    person.mArr = self.mArr;
 
  return person;
}
浅拷贝,对象两个,内容只有一个,改变其中一个对象的值,另一个也会访问到改变之后的值。但是要注意,字符串如果指向常量区,那么该值相当与重指向被,并不会影响另一个对象的值。

深拷贝:对象开辟空间,两个对象的实例变量也指向不同的内容,对象两份,内容两份,改变其中一个的值,内容不会改变。


//简述iOS内存管理?
    /*
     iOS内存管理方式是引用计数机制,通过控制对象的引用计数来实现操作对象的功能。一个对象的生命周期有生成、持有、释放、销毁。引用计数分为ARC、MRC,在MAC中,增加引用计数的方式为alloc、new、retain、copy,减少引用计数的方法为release、autorelease,当引用计数增减平衡时,系统会自动执行对象的dealloc方法,销毁对象,完成该对象的内存管理。
    
     Person *p = [[Person alloc] init];等价于Person *p = [Person new]; 但是new只能代表alloc和init,当init之后代参数就不能等价。
     */

7.内存管理

原文:http://www.cnblogs.com/aoliaoli/p/5196437.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!