Copy与mutableCopy的个人理解

1. 相同点

  • 都是将原有对象进行深拷贝(狭义)

    这里的狭义上的深拷贝指的是在不考虑编译器在编译时对不可变对象进行copy时采取的优化策略:即将不可变对象的地址直接赋值给拷贝对象,因为不可变对象无法进行修改,也就不存在拷贝后原值改变的情况,所以为了效率,即不再重新开辟空间,编译器对不可变对象采取了浅拷贝的方式

    浅拷贝 :只是对指针的拷贝,拷贝后两个指针指向同一个内存空间。

    深拷贝 :不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

  • 都是为了防止因原对象改变而造成拷贝对象改变的策略

    不可变对象除外

2.不同点

  • 无论是可变对象还是不可变对象进行copy,返回值一律是不可变对象(与被拷贝对象无关)

    可变对象copy后自然会拷贝一个新的地址给不可变类型的拷贝对象(深拷贝),而不可变对象因为优化策略则为浅拷贝

    NSMutableString* mstr=[NSMutableString stringWithString:@"1"];
    NSString *str=[mstr copy]; //将对象copy给不可变对象
    [mstr appendFormat:@"2"];//因为深拷贝,str不会因mstr改变而改变
    NSLog(@"%@",str); //输出1
    NSString* str0=@"1";
    NSMutableString *str1=[str0 copy];
    NSLog(@"%p:%p",str0,str1); //0x100001040:0x100001040 浅拷贝

    tips:当拷贝对象为可变对象时,使用copy会导致crash(在copy后使用append方法试图改变拷贝对象时)

    NSMutableString* mstr0=[NSMutableString stringWithString:@"1"];
    NSMutableString *mstr1=[mstr0 copy]; //将对象copy给可变对象
    [mstr0 appendFormat:@"2"];//因为深拷贝,mstr1不会因mstr0改变而改变
    NSLog(@"%@",str); //输出1
    [mstr1 appendFormat:@"2"];//crash,因为经过copy后mstr1已经变为了不可变对象(多态,NSMutableString是NSString的子类)
  • 无论是可变对象还是不可变对象进行mutableCopy,返回值一律是可变对象(与被拷贝对象无关,且狭义上深拷贝)

    狭义上的深拷贝指的是对于非容器类,而非容器类只是深拷贝容器,而容器内的对象则为指针拷贝(浅拷贝)

    容器类:NSArray、NSDictionary、NSSet

    如果要对容器类进行完全深拷贝,一般使用对象方法:-(id)initWithArray: copyItems:

    tips:当拷贝对象为不可变对象时,使用mutableCopy会将不可变对象改为可变对象

    NSString* str0=@"1";
    NSString *str1=[str0 mutableCopy]; //将对象mutableCopy给不可变对象
    [(NSMutableString *)str1 appendFormat:@"2"];//这里的str已经为可变对象,但编译器因为看不到可变对象的appendFormat方法,所以这里需要强转换为NSMutableString(若str这里不是真正指向可变对象,则会报错,但这里未报错,所以str已经指向了一个可变对象,即深拷贝)
    NSLog(@"%@",str1); //输出12

3.总结

无论是copy还是mutableCopy都可以看作是为了让被拷贝对象与拷贝对象进行分离,互不干扰的一种策略(通过深拷贝实现,虽然有两个例外:编译器优化(其实无影响)和容器类的假深拷贝)。只不过一个返回的是不可变对象,而另一个返回的是可变对象,仅此而已

最新文章

  1. Redis服务器的启动过程分析
  2. 我的CMS心路历程,DNN And Umbraco
  3. java 解析XML文档
  4. Lua基础之Function
  5. PCL 点云数据操作 OpenCV遍历数据
  6. jQuery分析(3) - jQuery.fn.init
  7. Android——service重启
  8. Ext.Ajax.request同步请求
  9. UFLDL实验报告3:Self-taught
  10. Matlab 矩阵运算
  11. 定义一个runtime的Annotation
  12. 四、Nginx负载均衡upstream
  13. 关于极光推送在手机系统低于iOS10的手机上闪退的问题。
  14. getNextElement( )函数——获取下一个特定的元素节点
  15. 如何解决Mac无法读取外置硬盘问题?
  16. 第二阶段第九次spring会议
  17. 并发包学习之-atomic包
  18. Electron 发生错误 "Cannot find module app"的解决方案
  19. Flume+HBase+Kafka集成与开发
  20. 解决XCode7.1 上无法安装 Alcatraz PackageManager

热门文章

  1. xpath爬虫实战-爬取小说斗罗大陆第四部
  2. 2019-2020-1 20199310《Linux内核原理与分析》第十一周作业
  3. printf 参数检查 __attribute__((format(printf, 1, 2)))
  4. [Qt] QlineEdit 限制输入,例如只能输入整数
  5. [Windows API] Listing the Files in a Directory,可用来数文件夹下有多少个子文件(夹)
  6. Component Object Model (COM) 是什么?
  7. D3.js 力导向图的显示优化
  8. layui表格参数
  9. Jenkins+Jmeter+Ant   生成测试报告
  10. 12c DG broker DMON自动重启过程分析