OC语言学习-内存管理


引用计数器

基本结构

  • 每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即该对象被多少个对象在引用

  • 每个OC对象内部专门有4个字节来存储引用计数器

引用计数器的作用

当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认为1

当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收,如果不为0,那么在整个程序运行过程中始终占据内存空间,除非整个程序退出

引用计数器的操作

1) 给对象发送一条retain消息,可以使引用计数器+1(retain方法返回值为对象本身

2) 给对象发送一条release消息,可以使引用计数器-1(没有返回值)

3) 可以给对象发送retainCount消息获得当前的引用计数器值

4) dealloc

  • 当一个对象要被回收的时候,就会调用dealloc

  • 重写dealloc方法时,一定要调用[super dealloc],且必须放在最后面

野指针:指向僵尸对象(不可用内存)的指针

僵尸对象:所占内存已经被回收的对象,僵尸对象不可再使用

空指针:没有指向任何东西的指针(存储的东西是nil、NULL、0)

多对象内存管理

1) 你要使用(占用)某个对象(set一个对象),就应该让对象的计数器+1(让对象做一次retain操作)

2) 你不再使用(占用)某个对象,就应该让对象的计数器-1(让对象做一次release)

3) 谁retain,谁release

4) 谁alloc,谁release

内存管理代码规范

只要调用了alloc,必须有release(autorelease)

没有调用alloc,就没有release(特殊对象:NSString对象,它不调用alloc,为直接赋值字符串对象)

set方法的代码规范
  • 基本数据类型

直接操作即可

  • OC对象类型
- (void)setCar:(Car *)car
{
      //1.先判断是否为新传进来的对象
      if(car!=_car)
      {
        [_car release];//(释放旧对象,执行release)换车时需对原来的车对象引用计数器进行-1
        _car=[car retain];//拥有一个新对象,对新对象做一次retain
      }
}

dealloc方法的代码规范

  1. 对将收回的对象所拥有的其他对象进行释放,执行release(没有对象引用,就没有release,如:单个对象

  2. 必须执行[super dealloc]

@Property的参数(即:带参数的@Property)

@Property所带的参数分为以下四类:

set方法内存管理相关的参数

  • retain :自动生成内存管理规范的set方法,即:release旧值,retain新值(适用于OC对象类型),如:@Property(retain) Car *car;

  • assign :直接赋值(默认,适用非OC对象类型)

  • copy :release旧值,copy新值

是否要自动生成set方法

  • readwrite:同时生成setter和getter的声明、实现(默认就是)

  • readonly:只生成getter的声明、实现

是否自动生成带有多线程管理

  • nonatomic:性能高(通常用这种)

  • atomic:性能低(默认)

是否自定义自动生成的setter和getter方法的名称

  • setter:自定义set方法的名称,注意带冒号:如:@property (setter=other age:) int age;

  • getter:自定义get方法的名称,(通常用于BOOL类型)

循环retain和@class

@class

作用:仅仅告诉编译器,某个名称是一类

开发中引用一个类的规范

在.h文件中用@class来声明类

在.m文件中用#import来包含类的所有东西

两端循环引用(即:你中有我,我中有你)解决方案

一端用retain,另一端用assign,否则会造成两个对象都无法被收回内存

autoreleasepool(自动释放池)

基本使用(autoreleasepool)

  • 会将对象放到一个自动释放池中

  • 当自动释放池被销毁时,会对池子里面的所有对象执行一次release操作

  • 会返回对象本身

  • 自动释放池存储于栈结构中


@autoreleasepool{
  Person *p=[[[Person alloc] init] autorelease];
}

好处

  • 不用关心对象释放的时间

  • 不用关心对象什么时候调用release

使用注意

  • 当对象占用内存空间较大时(如对象的成员变量有很多其他引用对象),不要使用自动释放池,应该使用release精确控制

  • 当对象占用内存的对象较小时,可以使用自动释放池,影响不大

实例

经验写法:

  • 开发中经常自定义一个类方法,这个类方法返回拥有引用自动释放池的对象,同时也可以传入一些参数

  • 创建对象的时候不要直接用类名,要用self(这样即使子类直接调用也不影响)

如:Person类

自定义类方法:

+ (id)person
{
   retrun[[[self alloc] init] autorelease];
}

根据需要也可自定义返回成员变量已拥有一定值的类方法

+(id)personWithAge:(int)age
{
    Person*p=[self person];
    p.age=age;
    return p;
}

编译器特性-ARC

基本原理

ARC判断准则:只要没有强指针指向对象,就会释放对象

指针分两种:

强指针:默认情况下,所有的指针都是强指针。定义格式:_ _strong

弱指针:_ _weak

ARC特点

不允许调用release、retain、retainCount

允许重写dealloc,但不允许调用[super dealloc]

  • @proerty参数

strong:成员变量是强指针 

weak:成员变量是弱指针

assign:同非ARC

ARC中的strong等价于非ARC中的retain

  • 循环调用

ARC中循环调用:一端用strong,另一端用weak


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值