当一个所有者(owner,其本身可以是任何一个Objective-C对象)做了以下某个动作时,它拥有对一个对象的所有权(ownership):

1. 创建一个对象。包括使用任何名称中包含“alloc”、“new”、或者“copy”的方法。

2. 保留(retain)一个对象。

一个对象可以有多个所有者,一个所有者也可以拥有多个对象。

相应的,引用计数增减的基本规则是:

1.当所有者创建一个对象时,该对象的引用计数为1。

2.当所有者保留它时,该对象的引用计数加1。

3.当所有者释放(release)它时,该对象的引用计数减1。

与此相关的,当一个所有者对于一个对象的引用计数的增减总计为0时,它放弃了对这个对象的所有权。

现在我们可以从两个不同的角度来看Objective-C的内存管理问题。从对象所有权的角度来看,当一个对象有着至少一个所有者(owner)的时候,它依然存在;当它没有任何所有者的时候,它会被释放掉。从引用计数的角度看,一个对象存在时,其引用计数大于零;当一个对象的引用计数为零时,它会调用dealloc方法并释放掉。这两个角度的关系是:在所有权的背后起作用的机制是引用计数机制;我们通过引用计数的增减来理解所有权的概念;但是你只应当使用所有权的概念来管理内存,因为如果你试图直接获取对象的引用计数,那么得到的数将让你感到匪夷所思——系统的一些框架会“偷偷”增减对象的引用计数。

回顾一下,内存管理的目标是:

当一个对象的某个所有者依然需要使用它时,保证这个对象的存在;当一个对象的所有所有者都不再需要它时,保证这个对象被销毁。因此只要任何一个所有者在使用完一个对象之后释放掉它,那么以上内存管理的目标就可以实现。

我们可以得出任何一个所有者(记住,所有者本身也只是一个对象)所应当遵守的基本步骤:

拥有一个对象 -> 使用一个对象 -> 放弃对象的所有权。

从引用计数的角度来看就是:

还需要这个对象时,保持对其增减为正;不再需要这个对象时,保持对其增减为0。

下图很好地诠释了这些基本规则:所有者1和所有者2单独地执行了拥有对象、使用对象、放弃对象所有权的步骤;当所有者1不再需要该对象时及时放弃了所有权,但此时所有者2依然拥有该对象,因此该对象依然存在,所有者2可以继续使用它;当所有者2也不再需要该对象时,也放弃掉所有权,这时对象以不再有任何所有者(相应的引用计数也变为0),因此立刻被销毁掉。

数计数的基本规则

需要注意的是,所有者2只是复制了该对象的指针,并没有使用copy方法,因此复制指针这个操作本身并不增加对象的引用计数;而正因为所有者2希望能使用该对象,因此通过retain方法成为它的所有者,也保证了所有者1放弃该对象时,对象不被销毁。

===========附上评论==========

1 | Hui

February 13th, 2011 at 10:18 pm

你画的这个图不对吧,右边这块owner应该先retain然后再让obj1指向这个对象吧。而且如果如果obj1不是nil, 应该先把原先的对象release掉吧。我也刚看到这里,无意中看到了你的Blog。

2 | 老召

February 16th, 2011 at 8:41 am

兄弟,看你技术不错,有兴趣加入我们吗?

我们是一家在上海的技术创业企业,目前主要做iphone/ipad/android上的游戏以及交互式展示应用开发(如3D动态电子出版物插页,移动AR增强现实应用)…… 具体的你可以去我们网站上看看。另外http://app.zealion.com是我们一些项目的sample展示。

自由、激情是我们的风格,有兴趣的话可以保持联系,兼职,全职,乃至参股共同创业,我们都不排斥。

3 | 雨雪霏霏

March 13th, 2011 at 5:29 am

@Hui: 感谢你的评论。这里为了介绍引用计数的增减,就没有涉及到obj1原先值的处理。 你说的是正确的,应当release掉原先的对象,但是在release之前还要做比较。对于所有者2来说,应当做: if (obj1 != obj) { [obj1 release]; obj1 = [obj retain]; }

4 | Xie Wei

May 22nd, 2011 at 2:33 am

原来是自己画的图啊,厉害厉害!

5 | cwang

July 2nd, 2011 at 7:18 am

是不是可以用autorelease延后释放,就不用比较了(比如在setter函数里面)

将下述代码

if (obj1 != obj) { [obj1 release]; obj1 = [obj retain]; }

改为

[obj1 autorelease]; [obj1 = [obj retain];

也是可以的吧?

6 | 雨雪霏霏

July 11th, 2011 at 2:57 am

cwang:感谢回帖!是的,使用autorelease会更简单明了。

7 | 非藉秋风

August 26th, 2011 at 4:51 am

看到《Objective-C基础教程》上的处理方法也挺好: [obj retain]; [obj1 release]; obj1 = obj; 苹果建议在iPhone开发中尽量不用autorelease。

iOS内存管理系列之一:对象所有权与引用计数的更多相关文章

  1. iOS内存管理机制解析之MRC手动引用计数机制

    前言: iOS的内存管理机制ARC和MRC是程序猿參加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了. iOS内存管理机制发展史 iOS 5 ...

  2. iOS 非ARC基本内存管理系列 2-多对象内存管理(1)

    单个对象的内存管理非常简单无非就是alloc对应release,retain对应release.但是如果涉及到很多对象,而且对象与对象有联系的时候该怎么去管理对象的内存呢. 比如同样一本书有好3个人购 ...

  3. iOS 非ARC基本内存管理系列 2-多对象内存管理(3) 利用@property来自动管理内存

    iOS 基本内存管理-多对象内存管理(2)中可以看到涉及到对象的引用都要手动管理内存:每个对象都需要写如下代码 // 1.对要传入的"新车"对象car和目前Person类对象所拥有 ...

  4. iOS 非ARC基本内存管理系列 2-多对象内存管理(2)

    /* 多对象内存管理: 以人拥有车为例涉及到@property底层set方法管理内存的实现 注意:人在换车的时候要进行当前传入的车和人所拥有的车进行判断 */ /******************* ...

  5. iOS内存管理系列之二:自动释放与便捷方法

    有时候一个所有者创建一个对象后,会立刻将该对象的指针传递给其它所有者.这时,这个创建者不希望再拥有这个对象,但如果立刻给它发送一个release消息会导致这个对象被立刻释放掉——这样其它所有者还没有来 ...

  6. python-面试常用 --变量、内存管理(小整数池,引用计数)

    执行Python程序的两种方法 第一种:交互式(jupyter就是对这种进行了封装) 优点:直接给出结果 缺点:无法保存 第二种:命令行式,通过Python解释器输入文本(pycharm对这种进行了封 ...

  7. 【Bugly干货分享】iOS内存管理:从MRC到ARC实践

    Bugly 技术干货系列内容主要涉及移动开发方向,是由Bugly邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 对于iOS程序员来说,内存管理是入门的 ...

  8. iOS内存管理(objective-c)

    移动app开发中,由于移动设备内存的限制,内存管理是一个非常重要的话题.objective-c的内存管理,不仅是面试当中老生常谈的一个必问话题,也是日常项目开发中,特别需要重视的环节.对于笔者这种以j ...

  9. iOS 内存管理(一)之基础知识介绍

    1,什么是引用计数 所有OC对象都有一个计数器,叫做引用计数,引用计数就是目前有几个对象在使用该对象(持有该对象的引用): 2,什么是对象所有权 A对象拥有B对象的引用,A对象拥有B对象的所有权: 3 ...

随机推荐

  1. [Javascript] delete keyword

    delete keyword doesn't actually delete the value but just the reference. var me = { name: { first: & ...

  2. 对MYSQL IFNULL函数的使用进行了具体的叙述

    下文对MYSQL IFNULL函数的使用进行了具体的叙述.供您參考学习.假设您在MYSQL IFNULL函数使用方面遇到过类似的问题,最好还是一看. MYSQL IFNULL(expr1,expr2) ...

  3. Data Types in the Kernel <LDD3 学习笔记>

    Data Types in the Kernel Use of Standard C Types /* * datasize.c -- print the size of common data it ...

  4. Cocos2d-x中常用粒子编辑器ParticleDesigner测试例子

    打开 ParticleDesigner 随意选择一种效果 选择save. 类型选择 cocosd(plist)类型保存至桌面 命名为myplist导出至桌面 选择右侧Emitter Config可设置 ...

  5. GUI之CCControlExtension

    Introduction CCControl is inspired by the UIControl API class from the UIKit library of CocoaTouch. ...

  6. Java基础知识强化之IO流笔记23:计算机是如何识别把两个字节拼接为中文(附加)

    1. 计算机是如何识别什么时候该把两个字节转换为一个中文呢? 在计算机中中文的存储分两个字节: • 第一个字节肯定是负数. • 第二个字节常见的是负数,可能有正数.但是没影响. 2. 代码示例: pa ...

  7. 【Android】数据存储-java IO流文件存储

    1.数据持久化:将在内存中的瞬时数据保存在存储设备中.瞬时数据:设备关机数据丢失.持久化技术提供一种机制可以让数据在瞬时状态和持久状态之间转换. 2.Android中简单的三种存储方式:文件存储.Sh ...

  8. PS之放射背景

    效果图 素材 新建图层,填充颜色 新建图层,矩形工具画条形 滤镜-扭曲-极坐标 合并图层,效果如下 新建图层,画一个适当的圆 滤镜-模糊-高斯模糊 将素材人物抠出来放在中间

  9. Unity3D 关于声音MissingComponentException报错

    如果你遇到报错如下: MissingComponentException: There is no 'AudioSource' attached to the "Level-2-bg&quo ...

  10. Lucene.net项目研究说明

    最近项目需要全文检索,所以找了几个开源的.NET检索项目,如:Lucene.net,Sphinx,Hubble.net.最后选择使用Lucene.ne来实现全文检索.至于原因嘛,可以参考下面几点: 1 ...