OC 内存管理(1)


oc 内存管理

基本原理
什么是内存管理
移动设备的内存极其有限,每个app所能占用的内存是有限制的
当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等
管理范围:任何继承了NSObject的对象,对其他基本数据类型(int、char、float、double、struct、enum等)无效


对象的基本结构


每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即有多少人正在使用这个OC对象
每个OC对象内部专门有4个字节的存储空间来存储引用计数器


引用计数器的作用
当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认就是1
当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收。换句话说,如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收,除非整个程序已经退出


引用计数器的操作
给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身)
给对象发送一条release消息,可以使引用计数器值-1
可以给对象发送retainCount消息获得当前的引用计数器值


对象的销毁
当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收
当一个对象被销毁时,系统会自动向对象发送一条dealloc消息
一般会重写dealloc方法,在这里释放相关资源,dealloc就像对象的遗言
一旦重写了dealloc方法,就必须调用[super dealloc],并且放在最后面调用
不要直接调用dealloc方法
一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)


 1.方法的基本使用
 1> retain :      计数器+1,会返回对象本身
 2> release :     计数器-1,没有返回值
 3> retainCount : 获取当前的计数器
 4> dealloc
  * 当一个对象要被回收的时候, 就会调用
  * 一定要调用[super dealloc],这句调用要放在最后面
 
 2.概念
 1> 僵尸对象 :所占用内存已经被回收的对象,僵尸对象不能再使用
 2> 野指针 :指向僵尸对象(不可用内存)的指针,给野指针发送消息会报错(EXC_BAD_ACCESS)
 3> 空指针 :没有指向任何东西的指针(存储的东西是nil、NULL、0),给空指针发送消息不会报错


看下面的例子:
#import <Foundation/Foundation.h>
#import "Person.h"


int main()
{
    
    Person *p = [[Person alloc] init];   //用alloc创建一个新对象p, p的引用计数器默认是1
    
    NSUInteger c = [p retainCount];      //retainCount用来获取对象当前计数器的值
    
    NSLog(@"计数器:%ld", c);            //输出的值为1;
    
    [p retain];                          // [retain]计数器加1:方法返回的是对象本身,现在是2
    
    [p release];                         // [release]计数器减1: 方法返回的是对象本身,现在是1
    
    [p release];                         // [release]计数器减1:现在是0; p指向一个死了的对象, p现在就是野指针, 指向了一个僵尸对象,               
    
    [p retain];                          // 当再[p retain]时会报后面的错误,-[Person setAge:]: message sent to deallocated instance 0x100109a10
    
    [p setAge:10];                       // 给已经释放的对象发送了一条-setAge:消息:同样报上面的错误
    
    p = nil;                             // 指针p变成空指针
 
                                         // EXC_BAD_ACCESS : 访问了一块坏的内存(已经被回收、已经不可用的内存
                                         // 野指针错误
    [p release];                         // OC不存在空指针错误,给空指针发送消息,不报错
    return 0;
}




只要还有人在用某个对象,那么这个对象就不会被回收
只要你想用这个对象,就让对象的计数器+1
当你不再使用这个对象时,就让对象的计数器-1


谁创建,谁release
如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease
换句话说,不是你创建的,就不用你去[auto]release


谁retain,谁release
只要你调用了retain,无论这个对象是如何生成的,你都要调用release


看下面的例子:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Book.h"


int main()
{
    
    Book *b = [[Book alloc] init];        //用alloc创建一本书,书的计数器现在为1; 
   
    Person *p1 = [[Person alloc] init];   //用alloc创建一个人,人得计数器现在为1
    
    [p1 setBook:b];                       //人想用这本是, 就给书的计数器加一  [b retain] p1现在计数器是1,b现在的计数器是2                       
    
    [p1 release];                         //人被释放了, p1的计数器现在变被0; 当p1挂掉以后,就去看他的遗言dealloc,再把它[retain]的书给释放掉[dealloc] b现在的计数器为1


    p1 = nil;                             //p1空指针
    
    [b release];                          //[b release] b现在的计数器是 0;
    b = nil;                              //b空指针
    return 0;
}
执行结果
 Person对象被回收
 Book对象被回收


---------------------------------------------------------------------------
#import "Book.h"
@implementation Book


- (void)setPrice:(int)price
{
    _price = price;
}


- (int)price
{
    return _price;
}
- (void)dealloc
{
    NSLog(@"Book对象被回收");
    [super dealloc];
}
@end
-----------------------------------------------------------------------------
#import "Person"
@implementation Person
- (void)setBook:(Book *)book
{
    _book = [book retain];
}


- (Book *)book
{
    return _book;
}


- (void)dealloc                                         //当人得计数为0时 自动执行dealloc
{
    [_book release];                                    //因为人[b retain]过, 所以当p1挂掉的时候, 就把以前的b释放掉 [b dealloc]
    NSLog(@"Person对象被回收");
    [super dealloc];
}
@end
-------------------------------------------------------------------------------

总结
有始有终,有加就有减
曾经让对象的计数器+1,就必须在最后让对象计数器-1



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值