标签:
ARC(Automatic Reference Counting),自动引用计数,是iOS中采用的一种内存管理方式。
指针变量暗含了对其所指向对象的所有权
当某个方法(或函数)有一个指向某个对象的局部变量时,可以称该方法(或函数)拥有该变量所指向的对象,如:
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSString *test = [[NSString alloc] init];
}
return 0;
}
上述代码中,main函数中有一个指向NSString的test对象,因此main函数拥有那个用相应的NSString对象。
当某个对象有一个指向其他对象的实例变量时,可以称该对象用用该实例变量所指向的对象。如:
@interface Item : NSObject
{
NSString *_itemName;
}
@end
上述代码中,我们声明一个Item类,在其头文件中创建一个NSString类型的实例变量_itemName,因此Item类型的对象拥有一个NSString对象。
对象所有权用于帮助我们决定是否应该释放某个对象并回收该对象占有的内存
如果某个对象没有拥有者,就应该将其释放掉。没有拥有者的对象是孤立的,程序无法向其发送消息。保留这样的对象只会浪费宝贵的内存空间,导致内存泄漏问题。
如果某个对象有一个或多个拥有者,就必须保留不能释放。如果释放了某个对象,但是其他对象或方法仍然有指向该对象的指针(准确地说,是指向该对象被释放前的地址),那么向该指针指向的对象发送消息就会使应用崩溃。释放正在使用的对象的错误称为过早释放。指向不存在的对象的指针称为空指针或者空引用。
对象失去拥有者的情况
当程序修改某个指向特定对象的变量并将其指向另一个对象时。
当程序将某个指向特定对象的变量设置为nil时。
当程序释放对象的某个拥有者时。
当从collection类中(例如数组)删除对象时。
所有权链条
因为对象可以拥有其他对象,后者也可以再拥有别的对象,所以释放一个对象可能会产生连锁反应,导致多个对象失去拥有者,进而释放对象并归还内存。
强引用:如果指针变量指向了某个对象,那么相应的对象就多一个拥有者,并且不会被程序释放,这种指针特性称为强引用。
弱引用:指针变量不影响其指向对象的拥有者个数。这种不会改变对象拥有者个数的指针特性称为弱引用。
弱引用非常适合解决强引用循环的内存管理问题。当两个或两个以上的对象相互之间有强引用特性的指针关联时,就会产生强引用循环。强引用循环会导致内存泄漏。当两个对象互相拥有时,将无法通过ARC机制来释放。即使应用中的其他对象都释放了针对这两个对象的所有权,这两个对象及其拥有的对象也无法释放。
iOS中属性后可以跟一组特性,用于描述相应存取方法的行为。这些特性写在@property指令后的小括号中。如:
@property (nonatomic, readwrite, copy) NSString *itemName;
其中,第一个特性用于描述属性的多线程特性,第二个特性用于描述属性的读/写特性,第三个特性用于描述属性的内存管理特性。strong、weak、copy
和unsafe_unretained
。 NSString *str0 = [NSString stringWithFormat:@"test"];
NSString *str1 = [str0 copy];
NSString *str2 = [str0 mutableCopy];
NSLog(@"The address of str0 is: %p", str0);
NSLog(@"The address of str1 is: %p", str1);
NSLog(@"The address of str2 is: %p", str2);
运行结果如下:
可见用copy的str1与str0的地址相同,而用mutableCopy生成的str2却与前面两者地址不同。
下面是一个NSArray类型的案例
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
//声明一个不可变数组,并初始化
NSArray *array0 = [NSArray arrayWithObjects:@"one", @"two", nil];
//用copy复制一个NSArray副本,浅拷贝
NSArray *array1 = [array0 copy];
//用mutableCopy复制一个NSArray副本,深拷贝
NSArray *array2 = [array0 mutableCopy];
//用copy复制一个NSMutableArray副本,浅拷贝
NSMutableArray *array3 = [array0 copy];
//[array2 addObject:@"three"];//可通过编译,但运行异常
//用mutableCopy复制一个NSMutableArray副本,深拷贝
NSMutableArray *array4 = [array0 mutableCopy];
[array4 addObject:@"three"];//编译和运行都可通过
NSLog(@"The address of array0 is: %p", array0);
NSLog(@"The address of array1 is: %p", array1);
NSLog(@"The address of array2 is: %p", array2);
NSLog(@"The address of array3 is: %p", array3);
NSLog(@"The address of array4 is: %p", array4);
}
return 0;
}
运行结果如下
可见,使用mutableCopy的array2、array4的地址与array0地址不同,其他用copy得到的地址都相同。
如果想要自定义的对象拥有复制特性,必须实现NSCopying,NSMutableCopying协议,实现该协议的copyWithZone方法和mutableCopyWithZone方法。深拷贝和浅拷贝的区别就在于copyWithZone方法的实现,
strong:默认属性,除了NSString/block外的OC对象都使用
weak:各种UI控件(不绝对,某些控件也要使用strong)
copy:copy创建的是不可变副本(imutable),而mutableCopy创建的是可变副本(mutable)
对于属性特性中的strong、weak等关键字,也有对应的局部变量版本。在局部变量前添加__strong就声明了一个强引用特性的局部变量。
另外,有了ARC之后,并不意味着程序员就完全不用手动管理内存了。ARC只能引用在OC对象上,如果涉及到底层的malloc()或者free(),ARC就无用武之地了,必须要程序员手动管理。此外,对于strong类型的指针,在不再使用之后,程序员也要手动设置为nil。
标签:
原文地址:http://www.cnblogs.com/scut-linmaojiang/p/5408731.html