——黑马程序员——OC加强部分 内存管理

本文深入探讨了Objective-C中的内存管理原理,包括对象所有权、引用计数、对象销毁过程、内存管理分类以及原则。同时提供了多种内存管理方式,如ARC、MRC和垃圾回收,并详细说明了单个对象和多对象的内存管理策略,以及如何避免内存泄露和野指针问题。文章还介绍了autorelease的基本使用、注意事项以及错误用法,旨在帮助开发者掌握Objective-C内存管理的核心知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-----------android培训java培训、java学习型技术博客、期待与您交流!-----------

OC内存管理的原理

一、OC内存管理的原理

范围:所有继承至 NSObject 的对象的内存管理,为了防止内存泄露

1、对象的所有权及引用计数

2、对象所有权:任何对象都可能拥有一个或者多个所有者,只要一个对象至少还拥有一个所有者,他就会继续存在

3、所有权策略:任何自己创建的对象都归自己所有,使用alloc new 或者copy的方法创建对象 , 都会有一个所有者,就是他自己,可以使用retain获取一对象的所有权

4、对象的引用计数器:用一个整数表示对象被引用的次数,对象创建时默认的引用计数是1,当引用计数变为0时,对象被销毁

5、引用计数器是判断对象要不要回收的依据就是计数器是否为0,若不为0则存在。 存在例外是:对象值为nil时,引用计数器为0时,但不回收空间

6、retain消息:使计数器+1,该方法返回对象本身

7、release消息:使计数器-1,并不代表释放对象

8、retainCount消息:存储引用计数器,获得当前引用计数器值  用%ld  %tu

二、对象销毁

1、当一个对象的引用计数器为0时,那么它将被销毁,占用的内存被系统回收

2、当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,释放相关的资源,delloc就像对象的”临终遗言“

3、一旦重写dealloc方法就必须调用 [ super dealloc ],并且放在代码块最后调用,不能直接调用dealloc方法

4、一旦对象被回收了,那么他所占用的存储空间就不再可用,坚持使用会导致程序崩溃,造成野指针错误

注意:

1、如果对象的计数器不为0,那么整个程序运行过程中,他所占用的内存就不可能被回收

2、任何一个对象,刚生下来的时候,引用计数器为1 ,当用alloc new 或者copy 创建一个对象时,对象的引用计数器默认就是1

三、OC中内存管理分类

提供三种内存管理方式

ARC、MRC 和垃圾回收(ios不支持垃圾回收)

四、内存管理原则

1、原则

只要有人使用某个对象,对象就不会被回收

如果想使用这个对象,就要让对象的引用计数+1

当不使用这个对象是,应该让对象引用计数器-1

 2、谁创建、谁release

(1)如果通过alloc new,copy 创建一个对象,就必须用release 或者autorelease方法,否则会内存泄露

(2)不创建就不负责

3、谁retain,谁release

(1)只要调用了retain,无论对象如何生成的,都要用release

4、内存管理的内容

(1)野指针(僵尸对象):1、定义的指针变量没有初始化   2、指向的空间已经被释放

(2)内存泄露:栈区指针释放,而堆区的空间没有释放,堆区的没有释放的空间发生内存泄漏

五、单个对象内存管理(野指针)

野指针访问:访问了一块(已经被回收的,不可用的)坏的内存

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

空指针:没有指向任何东西的指针,给空指针发送消息不会报错

nil :给一个对象赋值

Nil:给一个类赋值

NULL:通用指针

NSNull:[NSNull null]是一个对象,他用在不能使用nil的场合

注意

1、不能使用[p retain]让僵尸对象复活,已经死了不能复生

2、单个对象中避免使用僵尸对象的方法是:对象释放后,给对象赋值为nil

3 、单个对象的内存泄露情况之一是创建完成使用后,没有release

4、单个对象的内存泄露情况之二是使用retain后没有release

5、单个对象的内存泄露情况之三是nil的不当使用,对象被创建之后为release

例如:Dog *d = [ [ Dog alloc ] init ];

    d = nil;         //将对象赋值为nil(空)

     [d eat];        //对象调用方法时实质上是nil调用

                     [d release ]; //对象release时实质上是nil  release

6、单个对象的内存泄露情况之四是在方法中对传入的对象内部 retain 后,没有 release

六、多对象的内存管理

1、野指针问题的避免方法是:在方法内部进行retain

2、多对象中内存泄露解决方法是:在 dealloc方法中让别的对象release,也可以是使用  self.对象名 = nil

七、set方法中的内存管理

set方法的写法

如果在一个类中,有其他类的对象(关联关系例如凤姐开车去拉萨的例子)当有多个对象并且传给set方法的两个对象不一样时,前一个被传入的对象就会发生泄漏,因此需要下面的set写法,先判断传入的对象是不是新的,如果是新的就先release旧对象,再retain新对象,如果不是新的就直接将对象retain 一次

-(void)setCar:(Car *)car

{

//1、先判断是不是新传进来的对象

if( car != _car)

{

//2、对旧对象做一次release

[ _car release ];

//3、对新对象做一次retain

_car = [ car retain ];

}

}

八、对象作为另一个类的实例变量的固定写法

-(void)setDog:(Dog *)dog{

//1、判断对象否是原对象

if(_dog != dog) {

//release旧值

[ _dog release];

// retain新值,并且赋值给实例变量

_dog = [ dog retain ];

}

}

九、autorelease的基本使用

1、自动释放池

在ios程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的

当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中

2、自动释放池的创建

@autoreleasepool

{//开始代表创建自动释放池

.........

}//结束代表销毁自动释放池

3、autorelease基本用法

(1)创建自动释放池

@autoreleasepool

{//开始代表创建自动释放池

.........

}


(2)加入自动释放池,加入之后引用计数器不会发生变化

@autoreleasepool

{//开始代表创建自动释放池

[ 对象  autorelease ];

}//   此处自动释放池结束时会给池中的对象发送一条 release 消息,此时对象被释放

十、autorelease 的使用场景

1、经常用来在类方法中快速创建一个对象

十一、autorelease的注意事项

1、在MRC下,对象即使放到自动释放池的代码中,需要加入自动释放池中 ([对象 autorelease])才能释放;

2、如果对象没有放在任何一个自动释放池中,在自动释放池代码外面调用自动释放( [对象 autorelease];)对象也不会被释放

3、不管对象是在什么地方创建,只需在 自动释放池代码块中调用autorelease就可以把对象加入到自动释放池中释放

4、嵌套使用,autorelease只需加入一次,不能连续多次使用,和release不同

5、自动释放池不能放占用内存太大的对象

十二、autorelease错误用法

1、连续多次加入到autorelease中

2、alloc之后调用了autorelease,之后又调用了release

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值