OC中对象元素的引用计数 自动释放池的相关概念
一、数组对象是如何处理对象元素的引用计数问题
[objc] view plaincopy
1. //
2. // main.m
3. // 26_NSArrayMemeryManager
4. //
5. // Created by jiangwei on 14-10-12.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. #import "Dog.h"
12.
13. int main(int argc, const charchar * argv[]) {
14.
15. Dog *dog1 = [[Dog alloc] init];
16. Dog *dog2 = [[Dog alloc] init];
17.
18. NSMutableArray *array = [[NSMutableArray alloc] init];
19.
20. //数组会对每一个元素retain
21. [array addObject:dog1]; //dog1计数=2
22. [array addObject:dog2]; //dog2计数=2
23.
24. [dog1 release];
25. [dog2 release];
26.
27. //当数组销毁的时候,会将所有的元素release
28. [array release];//数组销毁
29.
30. //当数组移除所有的元素的时候,会讲所有的元素release
31. [array removeAllObjects];
32.
33. return 0;
34. }
我们定义了Dog类,然后定义了NSMutableArray数组存放两个Dog对象,OC中在将对象放到数组中的时候,会自动调用retain方法,当数组对象本身被销毁的时候,会调用所有元素的release方法,当移除数组中所有的元素的时候,会调用元素的release方法
二、自动释放池的概念
[objc] view plaincopy
1. //
2. // main.m
3. // 27_AutoReleasePool
4. //
5. // Created by jiangwei on 14-10-13.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. #import "Dog.h"
12.
13. int main(int argc, const charchar * argv[]) {
14.
15. /*
16. //创建一个自动释放池
17. //有作用域的问题,在{}中定义的东西外部是不能访问的,这点和NSAutoreleasePool有区别的
18. @autoreleasepool {//等价于[[NSAutoreleasePool alloc] init]
19.
20. Dog *dog2 = [[Dog alloc] init];
21. [dog2 retain];
22.
23. }//等价于[pool release]
24.
25. //创建一个自动释放池
26. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
27.
28. Dog *dog1 = [[Dog alloc] init];//计数:1
29.
30. //将dog1对象加入到自动释放池中,却别于之前的release方法
31. //加入到自动释放池中之后,不是代表我们不需要管理引用了,只是自动释放池自动会调用一次release
32. //当自动释放池销毁的时候,释放池会对池中每一个对象调用一次release
33. [dog1 autorelease];
34. NSLog(@"dog1计数:%ld",dog1.retainCount);
35.
36. //销毁自动释放池
37. //这时候会调用dog1的release方法,dog1对象就被销毁了
38. [pool release];
39. */
40.
41. //自动释放池的嵌套
42. NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];
43.
44. //添加我们的代码
45. //dog1放到了pool1中
46. Dog *dog1 = [[Dog alloc] init];
47. [dog1 autorelease];
48.
49. //自动释放池的嵌套
50. NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
51.
52. //dog2放到了pool2中
53. Dog *dog2 = [[Dog alloc] init];
54. [dog2 autorelease];
55.
56. //pool2销毁了
57. [pool2 autorelease];
58.
59. //pool1销毁了
60. [pool1 release];
61.
62.
63. //下面的代码就是有问题的
64. //[person setDog:[[Dog alloc] init];
65. //正确的写法
66. //Dog *dogs = [[[Dog alloc] init] autorelease];
67.
68.
69.
70. return 0;
71. }
我们在之前的文章中,定义一个对象的时候都会产生一个自动释放池,然后在释放池中编写我们的代码,自动释放池是系统提供的一种帮助我们去管理对象的引用计数问题。但是有时候代码必须在{...}中编写,这样的话就会产生作用域的问题,就是在{...}中定义的变量,在{...}外面不能使用。所以OC中就有了另外的一种方式:NSAutoreleasePool这个类
这种自动释放池可以实现嵌套
NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];
//write code...
//pool1销毁了
[pool1 release];
上面的代码就相当于建立了一个自动释放池pool1,但是在这个中间的代码,如果要加入到这个池中,必须调用autorelease方法:
[java] view plaincopy
1. //dog1放到了pool1中
2. Dog *dog1 = [[Dog alloc] init];
3. [dog1 autorelease];
而且,这样定义一个池子还可以嵌套使用,直接看上面的例子代码,这样这个自动释放池我们就可以控制了。比系统提供的自动释放池可操作的地方很多
下面就直接对比一下:
NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];
这行代码就相当于系统自动释放池的 {
[pool1 release];
这行代码就相当于系统自动释放池的 }
这样就好理解了吧
总结
这一篇文章主要介绍了OC中数组对象操作元素对象的时候需要处理的引用问题,以及我们可以自定义一个自动释放池,这种方式比系统提供的自动释放池方便,可操作性强。
OC中引用计数中一个痛疼的问题:循环引用.note
引用计数中一个痛疼的问题:循环引用
关于循环引用的问题,这里就不做太多解释了,就是多个对象之间相互引用,形成环状。
来看一个具体的例子:
Dog类和Person类之间相互引用
Dog.h
[objc] view plaincopy
1. //
2. // Dog.h
3. // 29_CyclePointer
4. //
5. // Created by jiangwei on 14-10-13.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. #import "Person.h"
12.
13. @interface Dog : NSObject
14.
15. //这里不用retain,如果使用retain的话,会形成循环引用
16. @property(nonatomic,assign,readwrite) Person *person;
17.
18. - (void)dealloc;
19.
20. @end
Dog.m
[objc] view plaincopy
1. //
2. // Dog.m
3. // 29_CyclePointer
4. //
5. // Created by jiangwei on 14-10-13.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import "Dog.h"
10.
11. @implementation Dog
12.
13. - (void)dealloc{
14. //[_person release];
15. NSLog(@"dog dealloc");
16. [super dealloc];
17. }
18.
19. @end
Dog类中有一个Person类型的属性
Person.h
[objc] view plaincopy
1. //
2. // Person.h
3. // 29_CyclePointer
4. //
5. // Created by jiangwei on 14-10-13.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. @class Dog;
12.
13. @interface Person : NSObject
14.
15. @property(nonatomic,retain,readwrite) Dog *dog;
16.
17. - (void)dealloc;
18.
19. @end
Person.m
[objc] view plaincopy
1. //
2. // Person.m
3. // 29_CyclePointer
4. //
5. // Created by jiangwei on 14-10-13.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import "Person.h"
10.
11. #import "Dog.h"
12.
13. @implementation Person
14.
15. - (void)dealloc{
16. [_dog release];
17. NSLog(@"Person dealloc");
18. [super dealloc];
19. }
20.
21. @end
Person类中有Dog类型的属性
看一下测试代码
main.m
[objc] view plaincopy
1. //
2. // main.m
3. // 29_CyclePointer
4. //
5. // Created by jiangwei on 14-10-13.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. #import "Dog.h"
12. #import "Person.h"
13.
14. //循环引用
15. //是一个很麻烦的一件事,完全靠经验
16. int main(int argc, const charchar * argv[]) {
17.
18. Person *p = [[Person alloc] init];
19. Dog *dog = [[Dog alloc] init];
20.
21. [p setDog:dog];//dog计数:2
22.
23. [dog setPerson:p];//person计数:2
24.
25. [p release]; //person计数:1
26. [dog release];//dog计数:1
27.
28. //没有释放的原因是dealloc方法中没有被执行,里面的释放代码也就没执行了,dog和person各自在等待,形成环状了
29. //解决版本就是切断他们之间的联系
30. //@property中不使用retain,使用assgin
31.
32. NSLog(@"is over");
33.
34. return 0;
35. }
我们分别定义了一个Person对象和Dog对象,然后相互引用了,但是当我们调用他们的release方法的时候,这两个对象并没有被释放
原因很简单:
person和dog的相互引用了,当执行release方法的时候引用计数都还是1,所以就不会调用dealloc方法了
dealloc方法中没有被执行,里面的释放代码也就没执行了,dog和person各自在等待,形成环状了
解决的办法是:
切断他们之间的联系
在一方中定义属性的时候,@property中不使用retain,使用assgin
同时在dealloc方法中不再调用release方法了
上面的例子中,我们可以看到Dog类中就是使用assgin
总结
OC中对象元素的引用计数 自动释放池的相关概念的更多相关文章
- OC学习篇之---数组对象的引用计数问题和自动释放池的概念
之前一片文章中我们介绍了OC中的两个关键字@property和@synthesize的使用的使用: http://blog.csdn.net/jiangwei0910410003/article/de ...
- OC之property和自动释放池
property实例 property参数 自动释放池 一.property实例 1.前边的例子我们看到,我们在一个类中如果用到另外一个类的实例作为自己的成员变量时,通常需要在setter方法中,先r ...
- objective-C 的内存管理之-自动释放池(autorelease pool)
如果一个对象的生命周期显而易见,很容易就知道什么时候该new一个对象,什么时候不再需要使用,这种情况下,直接用手动的retain和release来判定其生死足矣.但是有些时候,想知道某个对象在什么时候 ...
- (20)Cocos2d-x中的引用计数(Reference Count)和自动释放池(AutoReleasePool)
引用计数 引用计数是c/c++项目中一种古老的内存管理方式.当我8年前在研究一款名叫TCPMP的开源项目的时候,引用计数就已经有了. iOS SDK把这项计数封装到了NSAutoreleasePool ...
- OC_内存管理(二)对象复制、循环引用问题、自动释放池
循环调用: 1.循环引用的问题 两个对象A.B,有可能会出现特殊情况:A中包含B的实例变量:B中也包含A的实例变量,如果这两个实例变量都是强引用(A有着B的实例变量所有权,B也有A的实例变量所有权 ...
- [BS-21] 关于OC中对象与指针的思考
关于OC中对象与指针的思考 1. 创建对象: OC中可通过代码Person *p = [[Person alloc] init];创建了一个对象p.该过程中内存情况为: 在当前线程的栈(默认1M)中, ...
- OC中对象拷贝概念
OC中的对象拷贝概念,这个对于面向对象语言中都会有这种的问题,只是不同的语言有不同的解决方式:C++中有拷贝构造函数,Java中需要实现Cloneable接口,在clone方法中进行操作.但是不过OC ...
- OC对象,自动释放池,OC与C语言的区别
在C语言中,编程都是面向过程的编程,每一个代码块都严格按照从上至下的顺序执行,在代码块之间同样也是这样, 但是在OC中往往不是这样,OC和C++.java等语言一样,都是面向对象的编程语言,在代码的执 ...
- C++模拟OC的多重自动释放池
使用过OC的都知道,OC的引用计数机制用起来还比较方便.于是就仿照OC的形式搞了个C++引用计数. 支持多重自动释放池,每次autorelease都会放到栈顶的自动释放池中. 自动释放池也可以像变量一 ...
随机推荐
- linux C之access函数 (20
http://blog.sina.com.cn/s/blog_6a1837e90100uh5d.html linux C之access函数 (20access():判断是否具有存取文件的权限 相关函数 ...
- c++多线程崩溃错误1
主线程中的子线程没有jion,导致主线程马上结束,子线程对象被释放掉,而子线程还在后台继续执行导致崩溃 int main() OBJ = classA() OBJ.START()//在start函数中 ...
- ASP.Net MVC中数据库数据导出Excel,供HTTP下载
本文来自:http://www.cnblogs.com/hipo/archive/2012/03/13/2394019.html 一.关于下载 一般对下载权限有没有限制,或安全性要求不高的情况下,基于 ...
- andengine游戏引擎总结基础篇
其他的游戏引擎知道的不是很对,不过相对于学java的童鞋们来说,那是个不错的选择啦,这个发动机咋样,google去吧.基础篇包括图片,字体,音效,数据读取,会了这点,就会做简单的小游戏啦 对于游戏 ...
- Codeforces Round #258 (Div. 2/B)/Codeforces451B_Sort the Array
解题报告 http://blog.csdn.net/juncoder/article/details/38102391 对于给定的数组,取对数组中的一段进行翻转,问翻转后是否是递增有序的. 思路: 仅 ...
- 本地网址连不上远程mysql问题
问题:host 'XXX.XXX.XXX.XXX'is not allowed to connect to this MySQL server 解决办法: 进入远程mysql #mysql -u ro ...
- JDK安装与环境变量配置(Win7)
1.下载JDK(Java SE Development Kit) 地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-dow ...
- Django模板-分离的模板
上一篇Django模板-在视图中使用模板最后的问题,我们需要把数据和展现分离开. 你可能首先考虑把模板保存在文件系统的某个位置并用 Python 内建的文件操作函数来读取文件内容. 假设文件保存在 E ...
- VB生成xml
Dim text As XmlText Dim doc As New XmlDocument '加入XML的声明段落 Dim node As XmlNode = doc.CreateXmlDeclar ...
- Asp.net Mvc 中的模型绑定
asp.net mvc中的模型绑定可以在提交http请求的时候,进行数据的映射. 1.没有模型绑定的时候 public ActionResult Example0() { ) { string id ...