title: copy与mutableCopy的内存管理剖析
date: 2016-04-24 16:50:04

tags: copy

copy与mutableCopy相关的内存管理

不知道为什么一说这个,很多人都拿NSString和NSMutableString做测试,我想最直接的是因为常用又实现了copy和mutableCopy的代理,但是NSString类的其实比较特殊,不应该拿NSString来测试,所以本文拿实现代理的NSURLRequest来做测试。

immutableObject:

非集合的
NSURL *url = [[NSURL alloc] initWithString:@"ceshi"];NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:url];NSLog(@"urlReqeust:%@, urlRequestRec:%ld", urlRequest, [urlRequest retainCount]);  //log: urlReqeust: { URL: ceshi }, urlRequestRec:1

NSURLRequest *urlRequest1 = [urlRequest copy];
NSLog(@"urlRequest1:%@, urlRequest1:%ld", urlRequest1, [urlRequest1 retainCount]);
// log: urlRequest1: { URL: ceshi }, urlRequest1:2

总结:immutableObject做copy时,做的是浅copy,也就是说只是所指向的对象的内存计数器增加了1,所以如果urlRequest1重新赋值时,需要做下release把之前所指的对象的内存计数器减1,否则就会有内存泄露。如下:

[urlRequest1 release], urlRequest1 = nil;// 此时urlRequest所指对象计数器为1,urlRequest1为nilurlRequest1 = [NSURLRequest requestWithURL:[NSURL URLWithString:@"ceshi2"]];// 此时urlRequest1指向新的对象,指向的对象的计数器为1
集合的
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];NSArray *copyArray = [array copy];NSMutableArray *mCopyArray = [array mutableCopy];// log: =====array:0x7fb2a8f0d2b0,arrayRec:2, =====copyArray:0x7fb2a8f0d2b0,copyArrayRec:2, ======mCopyArry:0x7fb2a8e10ef0, mCopyArrayRec:1

// 有bug,必须要做copyArray的release

copyArray = @[@"a",@"d"];
NSLog(@"array:%@,copyArr:%@,mCopyArray:%@", array, copyArray, mCopyArray);
// log: =====array:0x7fb2a8f0d2b0,arrayRec:2, =====copyArray:0x7fb2a8f1b980,copyArrayRec:1, ======mCopyArry:0x7fb2a8e10ef0, mCopyArrayRec:1

与immutable的非集合一样,copy将直接增加指针指向对象的引用计数器(集合的话:各元素的指针计数器都增加了1)。所以在copyArray更改前,必须要做release,否则会有内存泄漏

mutableObject

非集合的
    NSURL *url = [[NSURL alloc] initWithString:@"ceshi"];
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:url];
NSLog(@"urlReqeust:%@, urlRequestRec:%ld\r", urlRequest, [urlRequest retainCount]);
// log: urlReqeust:<NSURLRequest: 0x7f98dac07e00> { URL: ceshi }, urlRequestRec:1NSMutableURLRequest *mutableRequest = [urlRequest mutableCopy];
NSLog(@"mutableRequest:%@, mutableRequest:%ld", mutableRequest, [mutableRequest retainCount]);
// log:  mutableRequest:<NSMutableURLRequest: 0x7f98daf07390> { URL: ceshi }, mutableRequest:1NSMutableURLRequest *mutableRequest1 = [mutableRequest mutableCopy];
NSLog(@"mutableRequest1:%@, mutableRequest1:%ld", mutableRequest1, [mutableRequest1 retainCount]);
// log: mutableRequest1:<NSMutableURLRequest: 0x7f98dac674f0> { URL: ceshi }, mutableRequest1:1
集合的
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];NSArray *copyArray = [array copy];NSMutableArray *mCopyArray = [array mutableCopy];// log: =====array:0x7fbbd3d0d730,arrayRec:1, =====copyArray:0x7fbbd3d19610,copyArrayRec:1, ======mCopyArry:0x7fbbd3d18ad0, mCopyArrayRec:1

总结:mutableObject的复制是深复制,直接创建一个新的内存地址来复制其内容(在集合中把各个元素的内容都赋值了一遍)。 与之前的被复制项无任何关系。

汇总:

  • [immutableObject copy] // 浅复制
  • [immutableObject mutableCopy] //深复制
  • [mutableObject copy] //深复制
  • [mutableObject mutableCopy] //深复制

特殊的NSString

NSString *str1 = @"abc";NSString *str2 = @"abc";NSString *str3 = [[NSString alloc] initWithString:@"abc"];NSString *str4 = [str1 copy];NSString *str5 = [[NSString alloc] initWithString:@"abc"];NSString *str6 = [str1 mutableCopy];

//输出内存中的地址
NSLog(@"str1: %p", str1);
NSLog(@"str2: %p", str2);
NSLog(@"str3: %p", str3);
NSLog(@"str4: %p", str4);
NSLog(@"str5: %p", str5);
NSLog(@"str6: %p", str6);

猜下结果:

2016-04-24 22:41:50.629 TestCopy[2094:229125] str1: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str2: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str3: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str4: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str5: 0x1081af070
2016-04-24 22:41:50.631 TestCopy[2094:229125] str6: 0x7fb1d3f0ce70

我的理解:
NSString在程序中使用非常大,所以在immutable的copy和mutableCopy的原理下,为了系统性能的考虑,增加了只要是NSString存在,则直接把字符串地址付给使用者即可。如果此时str2=@"abdt"了,则直接拿生成的abdt的地址赋值给str2即可。

NSMutableString与immutableObj类似

NSMutableString *str1 = [NSMutableString stringWithFormat:@"abc"];NSMutableString *str2 = [[NSMutableString alloc] initWithString:@"abc"];NSMutableString *str3 = [str1 copy];NSMutableString *str4 = [str1 mutableCopy];

//输出内存中的地址
NSLog(@"str1: %p, reC:%ld", str1, [str1 retainCount]);
NSLog(@"str2: %p, reC:%ld", str2, [str2 retainCount]);
NSLog(@"str3: %p", str3);
NSLog(@"str4: %p", str4);

log:
2016-04-24 22:58:42.319 TestCopy[2164:240308] str1: 0x7fa7ebca0c50, reC:1
2016-04-24 22:58:42.319 TestCopy[2164:240308] str2: 0x7fa7ebca8560, reC:1
2016-04-24 22:58:42.319 TestCopy[2164:240308] str3: 0xa000000006362613
2016-04-24 22:58:42.320 TestCopy[2164:240308] str4: 0x7fa7ebca7ed0

最后看2段代码:

//UserEntity.h@interface UserEntity : NSObject @property(strong, nonatomic) NSString *name;@endUserEntity *userEntity = [UserEntity new];//创建mutable类型的字符串NSMutableString *showName = [[NSMutableString alloc] initWithString:@"tutuge"];//先保存“tutuge”字符串到userEntity的nameuserEntity.name = showName;//修改showName[showName appendString:@" blog"];//输出userEntity的name属性NSLog(@"Name: %@", userEntity.name);

输出为:tutuge blog

如果更改为:@interface UserEntity : NSObject
@property(copy, nonatomic) NSString *name;
@end

则输出为: tutuge

copy与mutableCopy的内存管理剖析相关推荐

  1. Linux下ion内存,ION内存管理剖析.doc

    1.android之ION内存管理器(1)-- 简介 为什么需要ION 2011年末[2],LWN审查了android kernel patch[3],以期望将这些patch合并到kernel主线中. ...

  2. Linux内存管理剖析

    现在的服务器大部分都是运行在Linux上面的,所以作为一个程序员有必要简单地了解一下系统是如何运行的. 对于内存部分需要知道: 地址映射 内存管理的方式 缺页异常 先来看一些基本的知识,在进程看来,内 ...

  3. 内存管理-定时器循环、内存布局、tagged pointer、weak指针、copy、自动释放池

    先上代码,我们平时用的定时器,cadisplaylink.nstimer,CADisplayLink.NSTimer会对target产生强引用,如果target又对它们产生强引用,那么就会引发循环引用 ...

  4. iPhone/Mac Objective-C内存管理教程和原理剖析

    版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所有.欢迎非营利性转载,转载时必须包含原始链接http://vinceyuan.cnblogs.com/,且必 ...

  5. MySQL深潜|剖析Performance Schema内存管理

    简介: 本文主要是通过对PFS引擎的内存管理源码的阅读,解读PFS内存分配及释放原理,深入剖析其中存在的一些问题,以及一些改进思路. 一  引言 MySQL Performance schema(PF ...

  6. MYSQL深潜 - 剖析Performance Schema内存管理

    简介: 本文主要是通过对PFS引擎的内存管理的源码的阅读,解读PFS内存分配及释放原理,深入剖析其中存在的一些问题,以及一些改进思路.本文源代码分析基于Mysql-8.0.24版本. 作者 | 之枢 ...

  7. assign/retain/copy各内存管理特性的差异

    MRC下各内存管理特性 assign特性 当数据类型为int.float等原生类型时,可以使用assign,否则可能导致内存泄露.例如当使用malloc分配了一块内存,并把它的地址赋值给了指针a,后来 ...

  8. python内存管理和释放_《python解释器源码剖析》第17章--python的内存管理与垃圾回收...

    17.0 序 内存管理,对于python这样的动态语言是至关重要的一部分,它在很大程度上决定了python的执行效率,因为在python的运行中会创建和销毁大量的对象,这些都设计内存的管理.同理pyt ...

  9. 《Linux内核剖析》(Yanlz+VR云游戏+Unity+SteamVR+云技术+5G+AI+Makefile+块设备驱动+字符设备驱动+数学协处理器+文件系统+内存管理+GDB+立钻哥哥+==)

    <Linux内核剖析> <Linux内核剖析> 版本 作者 参与者 完成日期 备注 YanlzLinux_Kernel0.12_V01_1.0 严立钻 2020.02.06 # ...

最新文章

  1. windows中路径\和 linux中用/
  2. 手把手教你Tableau高级数据分析功能(附数据集)
  3. 精灵动画Animation对话框组成Idle动画的各精灵
  4. 使用Xmodem恢复交换机IOS
  5. windows 7 SDK和DDK下载地址
  6. 77. 组合016(回溯法)
  7. mybatis-启动源码分析
  8. STM32F1笔记(十)PWM
  9. python 字符串子串_Python字符串子字符串
  10. 毫米波雷达信号处理系统
  11. pl2303hxa串口线驱动_pl2303hx驱动下载
  12. EGM2008大地水准面模型在工程中的应用综述
  13. vscode配置和快捷键
  14. 女生29岁 ,想学前端,还来得及么?
  15. 《与韩荆州书》--李白经典求职信
  16. 内网渗透(五十二)之域控安全和跨域攻击-搭建和查看域信任关系
  17. 关于godot第三方功能增强版
  18. 豆芽的生长过程观察日记
  19. java opencv磨皮算法_美肤磨皮算法OpenCV3实现
  20. 阿里云服务器 远程桌面连接 卡顿

热门文章

  1. python debug工具_常用的 Python 调试工具,Python开发必读-乾颐堂
  2. Exception in thread main java.lang.NoSuchMethodError: scala.Predef$
  3. spring 扫描所有_SpringBoot和Spring到底有没有本质的不同?
  4. python作品_学习 Python 有些枯燥?那是你学错方法了,看这里
  5. Adobe Audition录制音频与剪辑
  6. python用辗转相除法求最大公约数
  7. 笔记-项目风险管理-转-从木桶效应谈对于安全管理的认识
  8. Python 办公自动化之一 Excel
  9. SqlServer 根据一个表数据更新另外一个表
  10. Winform中设置ZedGraph的曲线为折线、点折线、散点图