iOS copy和mutableCopy 整理
copy 和 mutableCopy 你真的理解吗?最近发现很多面试者基本都不能很好地回答这个问题。所以整理一下。
copy和mutableCopy的概念:
copy
浅拷贝,不拷贝对象本身,仅仅是拷贝指向对象的指针。
NSString *str1 = @"str1";
NSString *str2 = [str1 copy];
NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
/*输出结果,可以得出下图结论
str1 = str1 str1P = 0x104d75180
str2 = str1 str2P = 0x104d75180
*/
mutableCopy
深拷贝,是直接拷贝整个对象内存到另一块内存中。
NSMutableString *mStr1 = [@"123" mutableCopy];
NSMutableString *mStr2 = [mStr1 mutableCopy];
NSLog(@"\n mStr1 = %@ mStr1P = %p \n mStr2 = %@ mStr2P = %p", mStr1, mStr1, mStr2, mStr2);
/*输出结果,可以得出下图结论
mStr1 = 123 mStr1P = 0x6000004460c0
mStr2 = 123 mStr2P = 0x600000446420
*/
大部分人可能理解到这里就结束了。
当继续往下提问,如果是浅拷贝,改变str1的值,str2的值会变化吗?
问题1:上面浅拷贝的情况下,改变str1的值,str2的值会变化吗?
大部分人会不假思索的回答,因为str1 和 str2 指向同一个内存空间,str1变化,str2的值也会变化。
分析的很有道理,老铁看似没毛病毛病!
但是copy还有它的特点:
- 修改源对象的属性和行为,不会影响副本对象
- 修改副本对象的属性和行为,不会影响源对象
我们来试验一下:
NSString *str1 = @"str1";
NSString *str2 = [str1 copy];
str1 = @"asdf";
NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
/*输出结果,修改str2 同理
str1 = asdf str1P = 0x10776b1a0
str2 = str1 str2P = 0x10776b180
*/
那为什么NSString *str2 = [str1 copy];
是不同的指针指向同一块内存空间,str1 从新赋值 后两个内存空间就不一样了呢?
因为str2 = str1
的时候,两个字符串都是不可变的,指向的同一块内存空间中的 @"str1"
,是不可能变成@"abcd"
的。所以这个时候,为了优化性能,系统没必要另外提供内存,只生成另外一个指针,指向同一块内存空间就行。
但是当你从新给 str1
或者str2
赋值的时候,因为之前的内容不可变,还有互不影响的原则下,这个时候,系统会从新开辟一块内存空间。
问题2:copy 一个可变的数组,会出现什么结果?
我们直接上结果吧。。。
NSMutableArray *mArr1 = [@[@"123", @"456", @"asd"] mutableCopy];
NSMutableArray *mArr2 = [mArr1 copy];
NSLog(@"\n mArr1 = %@ mArr1P = %p mArr1 class = %@ \n\n mArr2 = %@ mArr2P = %p mArr2 class = %@", mArr1, mArr1, [mArr1 class], mArr2, mArr2, [mArr2 class]);
/*输出结果
mArr1 = (
123,
456,
asd
)
mArr1P = 0x60400025db20
mArr1 class = __NSArrayM
mArr2 = (
123,
456,
asd
)
mArr2P = 0x60400025dd30
mArr2 class = __NSArrayI
*/
从结果看出,内存地址不一样,而且mArr2
是不可变的。copy
为什么不是指针指向了?
首先,mArr2
是通过copy
得来的,关键点在于copy
,和mArr1
无关,所以他是不可变的。
另外,mArr1
指向的内存空间是可变的,如果对mArr1
进行修改,同一内存空间的内容就会变化。 遵循相会不影响的原则,加上mArr2
是不可变的,mArr1
的内存空间已经不合适,所以此时的 copy
从新开辟内存空间。
问题3:用 copy 修饰 NSMutableArray @property (nonatomic, copy) NSMutableArray *mArr;
,对mArr 赋值会有什么结果?
NSArray *arr = @[@"123", @"456", @"asd"];
self.mArr = [arr mutableCopy];
NSLog(@"\n arrP = %p \n self.mArrP = %p, self.mArr class = %@", arr, self.mArr, [self.mArr class]);
/*输出结果
arrP = 0x60000044d1a0
self.mArrP = 0x60000044d1a0, self.mArr class = __NSArrayI
*/
可以看出内存地址不一样,但是_mArr
是不可变的数组。
因为 _mArr
声明的时候是用 copy
修饰,那么就限制了他为不可变的数组。 赋值的时候是用mutableCopy
,可变数组的复制方法,所以会从新分配内存。
NSArray *arr = @[@"123", @"456", @"asd"];
self.mArr = arr;
NSLog(@"\n arrP = %p \n self.mArrP = %p, self.mArr class = %@", arr, self.mArr, [self.mArr class]);
/*输出结果
arrP = 0x60400044ecd0
self.mArrP = 0x60400044ecd0, self.mArr class = __NSArrayI
*/
直接赋值,内存地址没变。
问题4:浅拷贝,不拷贝对象本身,仅仅是拷贝指向对象的指针。深拷贝,是直接拷贝整个对象内存到另一块内存中。 有什么看法?
浅拷贝,不拷贝对象本身,仅仅是拷贝指向对象的指针。不够严谨,在一些特殊请款下,还是会拷贝整个对象内存到另一块内存中。
总结:
- 用copy修饰的 或者赋值的 变量肯定是不可变的。
- 用copy赋值,要看源对象是否是可变的,来决定只拷贝指针,还是也拷贝对象到另一块内存空间
- 对象之间mutableCopy赋值,肯定会拷贝整个对象内存到另一块内存中
- 对象之间赋值之后,再改变,遵循互不影响的原则
iOS copy和mutableCopy 整理的更多相关文章
- iOS Copy 和 MutableCopy的区别 深浅拷贝的区别-供参考
概述 对于系统的非容器类对象,对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝).如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的. 对于 ...
- iOS copy 和 mutableCopy 学习
(参考 iOS 52个技巧学习心得笔记 第二章 对象 , 消息, 运行期)的对象部分 关于Copy 有个经典问题”大部分的时候NSString的属性都是copy,那copy与strong的情况下到底 ...
- iOS copy&mutableCopy理解
Copy&mutableCopy 通过copy方法可以创建可变或不可变对象的不可变副本,通过mutableCopy可以创建可变或不可变对象的可变副本. 拷贝分为浅拷贝和深拷贝: 浅拷贝:指 ...
- iOS之NSArray类簇简介-(copy、mutableCopy导致程序crash)
1.前言 开发时常常用数组对数据进行处理,对NSMutableArray进行操作时经常导致程序崩溃,特研究一下NSArray的类簇!涉及__NSPlaceholderArray.__NSArray0. ...
- [Objective-C] Copy 和 MutableCopy
看了几篇文章,因为文章很新手向,所以内容很繁琐.故整理一下重点,写了测试程序去了解几个知识点,不讨论基本概念.新博客wossoneri.com传送门 非集合类对象的copy与mutableCopy / ...
- iOS学习笔记-精华整理
iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...
- 转载一篇关于ios copy的文章
由于原文创作时间较早,一些内容不实用了,我对其进行了加工,去掉了一部分内容,添加了一点注释. 原文连接 http://www.cnblogs.com/ydhliphonedev/archive/201 ...
- iOS学习笔记总结整理
来源:http://mobile.51cto.com/iphone-386851_all.htm 学习IOS开发这对于一个初学者来说,是一件非常挠头的事情.其实学习IOS开发无外乎平时的积累与总结.下 ...
- 【转】copy 和 mutablecopy (深拷贝和浅拷贝)
阅读本文之前首先了解copy与retain的区别,如果有不正确的地方望大家多多指教: copy与retain的区别: copy是创建一个新对象,retain是创建一个指针,引用对象计数加1.Copy属 ...
随机推荐
- Access与SQL中的IsNull(),IS NULL的区别
Access也有IsNull函数,但意义和参数却和T-SQL中的不同. 在T-SQL(也就是SQL Server所支持的SQL语言)中,IsNull的作用是把空值替代成指定的值.然而在Access中, ...
- pls_integer类型
转: pls_integer类型 2011-08-22 16:49:06 heqiyu34 阅读数 13413更多 分类专栏: Oracle 今天在看一个触发器代码的时候碰到了一个pls_inte ...
- SVL-VI SLAM
3.4. Mappoints management and key frame process如果在步骤3.3中成功跟踪地图点,则缓存地图点以在下一帧中优先化.当完成当前帧的跟踪时,应该为下一帧更新帧 ...
- 中标麒麟+Qt+mysql解决驱动无法加载的问题
问题描述:都安装了Qt,Mysql之后,发现Qt始终不能连接Mysql 1.安装Qt 2.写程序直接连接QMysql 打印QSqlDatabase: * driver not loaded ,进入/h ...
- 用KNN实现iris的4分类问题&测试精度
import matplotlib.pyplot as plt from scipy import sparse import numpy as np import matplotlib as mt ...
- 面向对象(实际就像python跳用自己写的库那样)
被调用的对象(库) FanFa.java 文件 package com.BM; public class FanFa { #变量值 int r=4 #方法 public static void uui ...
- sriov-网络问题Debug记录
我司容器云平台使用了sriov的底层网络模型,这个网络驱动的好处是配置少,转发效率高,但是缺点也很明显,出了问题比较难Debug. 现就工作中出现的问题记录如下: 容器删除后,或者docker进程异常 ...
- 洛谷 题解 P1550 【[USACO08OCT]打井Watering Hole】
本题看似很难,实际上思路非常简单--如果你想通了. 首先有一个问题:图中有几个点?大部分的人会回答\(n\)个点.错了,有\(n+1\)个. 多出来的那个点在哪?关键在于你要理解每一个决策的意义.实际 ...
- linux打印指定的行的内容
使用sed打印第99行 sed -n '99,p' test.txt 使用awk打印第99行 awk 'NR==99' test.txt awk 'FNR==99' test.txt perl 完成 ...
- hdoj4099(字典树+高精度)
题目链接:https://vjudge.net/problem/HDU-4099 题意:给T组询问,每个询问为一个字符串(长度<=40),求以该字符串为开始的fibonacci数列的第一个元素的 ...