漫步IOS--引用计数函数和深浅拷贝

来源:互联网 发布:ajax json遍历 编辑:程序博客网 时间:2024/06/04 19:25

引用计数函数

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的话,只是简单地数据地址的传递,对于该实例变量来说其实并没有进行空间创建和数据拷贝。而上面示例代码中的方式是进行了空间创建和数据拷贝的。

0 0