一个oc对象的引用计数时机
最近冥想一个这样的问题:我们都知道ARC机制是一种简单有效地管理oc对象生命周期的方式,当一个实例被创建的时候,实例的引用计数会变成1,当一个新的指针指向实例的时候,它的引用计数会变成2,当没有指针指向这个实例的时候它的引用计数会变成0,这个时候ARC机制会销毁该实例并回收内存...
那么一个继承于NSObject
类的实例,其引用计数是什么时候第一次被+1的呢,是alloc
的时候,还是init
的时候,还是时候呢?
这是一个非常基础的问题,我们分为下面三种情况分析下
情况1:
其实我们知道新实例被创建后,只要被强引用了,其引用计数必然会+1,那么在一个函数中如果我们只创建了一个实例:
- (void)test {
[[NSObject alloc] init];
}
此实例的引用计数是怎么样的呢?
我们知道alloc
的时候实例的内存被分配,init
的时候实例内部的属性等会被创建,但是其没有被任何对象或者属性引用,可以认为是没有被指针指向的,所以此时实例的引用计数为0
,当执行完test
函数后,实例会被销毁。
情况2:
- (void)test {
NSObject *obj = [[NSObject alloc] init];
NSLog(@"引用计数:%lu", (unsigned long)[obj retainCount]);
}
那如果是这样,其实例的引用计数会是多少呢?
答案是:引用计数:1
,因为实例被创建后,被obj
变量的指针所指向了,也就是说objc
变量持有了该实例,所以打印的结果会是1
。同样的,当执行完test
函数后,实例会被销毁。
情况3:
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic, strong) NSObject *obj;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self test];
NSLog(@"引用计数:%lu", (unsigned long)[self.obj retainCount]);
}
- (void)test {
NSObject *obj = [[NSObject alloc] init];
NSLog(@"引用计数:%lu", (unsigned long)[obj retainCount]);
self.obj = obj;
NSLog(@"引用计数:%lu", (unsigned long)[obj retainCount]);
}
@end
此时两次的log是如何呢?
答案是:引用计数:1
、引用计数:2
、引用计数:2
。[[NSObject alloc] init]
实例创建后被obj
和self. obj
两个变量的指针指向了...函数结束后,因为ViewController
持有self. obj
,self. obj
持有着实例,所以其引用计数不会为0
。
引用计数和方法作用域
在上述情况2中最终[[NSObject alloc] init]
实例会被销毁呢?
答案是和函数的作用域有关系的,函数中的局部变量是在栈
中,比如情况2中的obj
变量,其本质就是一个指针,在函数结束的时候,系统就会释放这个指针。所以函数结束时,就没有指针指向实例,其引用计数为0
,在ARC的环境下就会自动销毁该实例。
如果你想了解iOS的内存存储区域、循环引用&解决循环引用的本质,可以转到iOS内存管理基础1。
网友评论