copy的内存管理
首先理解一下深复制和浅复制:
- 深复制
源对象和副本对象是不同的两个对象;
源对象引用计数器不变,副本对象计数器为1(因为是新产生的);
本质是:产生了新的对象。 - 浅复制
源对象和副本对象是同一个对象
源对象(副本对象)引用计数器+1,相当于做一次retain操作;
本质是:没有产生新对象。
注意:只有源对象和副本对象都不可变时,才是浅拷贝,其他都是深拷贝
NSString *str1 = [NSString stringWithFormat:@"address is only one"];
NSString *str2 = [str1 copy];
NSLog(@"%p ,%p",str1,str2);
//结果发现两个地址一样,都是0x610000052990。
/**
1.copy:产生的肯定是不可变副本
2. 如果是不可变对象调用copy方法产生出不可变副本,那么不会产生新的对象
*/
1. NSMutableString调用mutableCopy : 深复制。
2. NSMutableString调用copy : 深复制。
3. NSString调用mutableCopy : 深复制。
4. NSString调用copy : 浅复制
__strong
当一个对象被强指针指向则引用计数就加1,否则,该对象没有一个强指针指向则自动释放内存
原理:
__weak
id __weak obj = [[NSObject alloc] init];
可以知道NSObject对象在生成之后立马就会被释放,其主要原因是__weak修饰的指针没有引起对象内部的引用计数器的变化
原理:
- 修饰的指针不会引起指向的对象的引用计数器变化
id obj;
id tmp = objc_msgSend(NSObject,@selector(alloc));
objc_msgSend(tmp,@selector(init));
objc_initweak(&obj,tmp);
objc_release(tmp);
objc_destroyWeak(&object);
对于__weak内存管理也借助了类似于引用计数表的表,它通过对象的内存地址做为key,而对应的指针作为value进行管理,在上述代码中objc_initweak就是完成这部分操作,而objc_destroyWeak
则是销毁该对象对应的value。所以,weak在修饰只是让weak表增加了记录没有引起引用计数表的变化
- 当指向的对象被销毁时,弱指针全部置为nil
原理:
1)从weak表中获取已废弃对象内存地址对应的所有记录
2)将已废弃对象内存地址对应的记录中所有以weak修饰的变量都置为nil
3)从weak表删除已废弃对象内存地址对应的记录
4)根据已废弃对象内存地址从引用计数表中找到对应记录删除
网友评论