引用计数函数
1 alloc
开辟内存空间,让被开辟的空间的引用计数变为1,这是从0到1得过程
什么时候看到alloc什么时候开辟空间。
类方法是没办法去调用实例方法的,也没办法改变实例变量。凡是一次alloc配套一次release或者autorelease。
2 retain
引用计数+1,他的作用是将对象的指针指向一个内存,而并不需要去开辟新的空间。
凡是一次retain配套一次release或者autorelease。
3 copy
开辟一个新的空间,引用计数为1。他的作用是将内存中的数据进行拷贝,并在内存中开辟一个新的空间,并将刚才拷贝的数据赋值进去。然后将对象的指针指向新开辟的空间。
凡是一次copy配套一次release或者autorelease。如果使用Copy这个方法,必须实现一个协议,NSCopying或者NSMutableCopying。
4 release
引用计数-1,在release的时候要注意的是,要重写dealloc。类中包含的实例变量如果是也是一个实例的话,
retainCount有一个特性,在将要由1变为0的时候,直接释放内存,但是retainCount的值还是1,没有重写为0.
这里科普一下野指针。野指针:实例变量虽然已经释放了,但是通过某些方法,依旧知道指针的地址,还是可以去访问,这就是野指针。
5 dealloc
在对象的引用计数为0的时候会自动的调用。一些在释放前需要进行的操作可以写在这里,例如调用父类的dealloc销毁从父类继承过来的实例变量,销毁自身实例变量的空间等等。
6 autorelease ,要配合@autoreleasepool{}使用。autorelease并不会立即对引用计数减1,在花括号结束的时候,会对引用计数进行减1操作。
具体用法代码:
@autoreleasepool {
Person *p = [[Person alloc] init];
p.name = @"夜吹雪";
p.books = @[@"人生-路遥",@"他们最幸福-大冰"];
[p autorelease];
}
自动释放池是一种栈结构,每当遇到一个Autorealease就将他入栈,当出了自动释放池,将栈中所有的对象引用计数减1,最后入栈的最先减1.
深浅拷贝
OC中也存在深浅拷贝,在OC中的深拷贝是NSMutableCopying,浅拷贝是NSCopying。
所谓的浅拷贝,就是只把目标对象的指针拷贝过来,其余的啥也不做。
所谓的深拷贝,就是把目标对象的数据(包括实例变量和方法)全部拷贝,然后另开一个新空间存储,返回指针。就是指针和数据的全拷贝。
具体在OC中实现的代码是:
- (id)copyWithZone:(NSZone *)zone{
//浅拷贝
// return [self retain];
//深拷贝
Person *p = [[Person allocWithZone:zone]init];
p.name = [NSString stringWithFormat:@"%@",self.name];
p.books = [NSArray arrayWithArray:self.books];
return p;
}
注意,上面对于p.name的赋值,没有采用self.name的原因是这些实例变量在定义的时候都是定义的指针,那么如果是p.name = self.name的话,只是简单地数据地址的传递,对于该实例变量来说其实并没有进行空间创建和数据拷贝。而上面示例代码中的方式是进行了空间创建和数据拷贝的。