Objective-C:OC内部可变对象和不可变对象的深(复制)拷贝问题思考:
OC内部:可变对象和不可变对象的深(复制)拷贝问题思考:
1:对于不可变对象,copy都是浅复制,即指针复制。mutableCopy 都是Alloc一个新对象返回。
2:对于可变对象,copy和mutableCopy都是Alloc新对象返回。
3:不论是可变还是不可变对象,copy返回的对象都是不可变的,mutableCopy返回的对象都是可变的。
4:容器类对象,不论是可变的还是不可变的,copy,mutableCopy返回的对象里所包含的对象的地址和之前都是一样 的,即容器内对象都是浅拷贝。
一、不可变对象的深复制
// Person.h
// 测试
//
// Created by ma c on 15/8/15.
// Copyright (c) 2015年. All rights reserved.
// #import <Foundation/Foundation.h> @interface Person : NSObject<NSCopying>
@property(nonatomic,copy)NSString *name;
-(id)initWithName:(NSString *)name;
-(void)print;
@end
// Person.m
// 测试
//
// Created by ma c on 15/8/15.
// Copyright (c) 2015年. All rights reserved.
// #import "Person.h" @implementation Person
-(id)initWithName:(NSString *)name
{
self = [super init];
if(self)
{
_name = [name mutableCopy]; //不可变深复制mutableCopy
//_name = [name copy];//不可变深复制copy
}
return self;
} -(id)copyWithZone:(NSZone *)zone
{
return [[Person alloc]initWithName:_name];
}
@end
主函数测试
- // main.m
- // 测试
- //
- // Created by ma c on 15/8/15.
- // Copyright (c) 2015年. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "Person.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool
- {
- NSMutableString *name = [NSMutableString stringWithString:@"Jobs"];
- Person *p1 = [[Person alloc]initWithName:name];
- NSLog(@"%@----%p",name,p1.name);
- Person *p2 = [p1 copy];
- NSLog(@"%@----%p",name,p2.name);
- [name appendString:@"Tom"];
- Person *p3 = [[Person alloc]initWithName:name];
- NSLog(@"%@----%p",name,p3.name);
- Person *p4 = [p3 copy];
- NSLog(@"%@----%p",name,p4.name);
- }
- return 0;
- }
测试结果如下:
2015-08-15 22:14:33.544 测试[2042:151149] Jobs----0x100206d10
2015-08-15 22:14:33.545 测试[2042:151149] Jobs----0x100300360
2015-08-15 22:14:33.545 测试[2042:151149] JobsTom----0x100300410
2015-08-15 22:14:33.545 测试[2042:151149] JobsTom----0x100400010
Program ended with exit code: 0
以上结果为mutableCopy深复制的结果:复制后一样的内容,可是各自所在的地址值是不同的,说明了系统为新创建的对象开辟了内存,这就是真正意义的深复制。
2015-08-15 22:15:08.773 测试[2050:151390] Jobs----0x100206d10
2015-08-15 22:15:08.774 测试[2050:151390] Jobs----0x100206d10
2015-08-15 22:15:08.775 测试[2050:151390] JobsTom----0x100207810
2015-08-15 22:15:08.775 测试[2050:151390] JobsTom----0x100207810
Program ended with exit code: 0
以上结果为copy深复制结果,可以看出复制后一样的内容,可是它们的地址值是一样,说明了这并不是真正意义的深复制,而是假深复制,即最终结果是只是复制了指针。
二、可变对象的深复制
// Person.h
// 测试
//
// Created by ma c on 15/8/15.
// Copyright (c) 2015年. All rights reserved.
// #import <Foundation/Foundation.h> @interface Person : NSObject<NSCopying>
@property(nonatomic,copy)NSMutableString *name;
-(id)initWithName:(NSMutableString *)name;
-(void)print;
@end
// Person.m
// 测试
//
// Created by ma c on 15/8/15.
// Copyright (c) 2015年. All rights reserved.
// #import "Person.h" @implementation Person
-(id)initWithName:(NSMutableString *)name
{
self = [super init];
if(self)
{
//_name = [name copy];//可变深复制copy
_name = [name mutableCopy];//可变深复制mutableCopy
}
return self;
}
-(id)copyWithZone:(NSZone *)zone
{
return [[Person alloc]initWithName:_name];
}
@end
主函数测试
// main.m
// 测试
//
// Created by ma c on 15/8/15.
// Copyright (c) 2015年. All rights reserved.
// #import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[])
{
@autoreleasepool
{
NSMutableString *name = [NSMutableString stringWithString:@"Jobs"]; Person *p1 = [[Person alloc]initWithName:name];
NSLog(@"%@----%p",name,name);
NSLog(@"%@----%p",p1.name,p1.name); }
return ;
}
测试结果如下:
-- ::12.110 测试[:] Jobs----0x1001002d0
-- ::12.111 测试[:] Jobs----0x100106c90
Program ended with exit code: 以上结果为可变对象的复制,采用copy复制时,复制出的内容是一样的,但是它们的地址值是不相同的,所以这是真正意义的深复制。
-- ::05.744 测试[:] Jobs----0x1001147a0
-- ::05.745 测试[:] Jobs----0x100114a40
Program ended with exit code: 以上结果为可变对象的复制,采用mutableCopy复制时,复制出的内容也是一样的,但是它们的地址值也是不同的,这也是真正意义的深复制。
Objective-C:OC内部可变对象和不可变对象的深(复制)拷贝问题思考:的更多相关文章
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
读前小提示:对于深浅复制有一个清楚的了解,对于学习oc的朋友来说,至关重要.那么首先,我们要明白深浅复制是如何定义的呢.这里为了便于朋友们理解,定义如下. 浅 复 制:在复制操作时,对于被复制的对象的 ...
- Objective-C:MRC(引用计数器)在OC内部的可变对象是适用的,不可变对象是不适用的(例如 NSString、NSArray等)
引用计数和字符串 内存中的常量字符串的空间分配与其他对象不同,他们没有引用计数机制 凡是自定义的对象都有引用计数机制: OC内部中对象分为可变对象(NSMutableString等)和不可变对象(NS ...
- Java基础知识强化101:Java 中的 String对象真的不可变吗 ?
1. 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...
- 区分Python中的可变对象和不可变对象
参考: https://www.cnblogs.com/sun-haiyu/p/7096918.html """不过注意函数传参既不是传值也不是传引用,正确的叫法是传对象 ...
- python 中的可变对象与不可变对象
近日辞职待工,没有实际的项目与大家分享.暂写写在实际运用python中遇到的关于可变对象和不可变对象的坑. 首先我们需要明确一个概念,在python中一且皆对象.我们一般定义一个变量a=0,其实质a是 ...
- String对象为什么不可变
转载:https://www.cnblogs.com/leskang/p/6110631.html 一.什么是不可变对象? As we all know, 在Java中, String类对象是不可变的 ...
- Python中的不可变对象类型与可变对象类型
https://blog.csdn.net/answer3lin/article/details/86430074 其实各个标准资料中没有说明Python有值类型和引用类型的分类,这个分类一般是C++ ...
- 【Python】可变对象和不可变对象
Python在heap中分配的对象分成两类:可变对象和不可变对象.所谓可变对象是指,对象的内容是可变的,例如list.而不可变的对象则相反,表示其内容不可变. 不可变对象:int,string,flo ...
- Python 可变对象和不可变对象
具体可以看这里:http://thomaschen2011.iteye.com/blog/1441254 不可变对象:int,string,float,tuple 可变对象 :list,dicti ...
随机推荐
- MySQL性能优化(七·下)-- 锁机制 之 行锁
一.行锁概念及特点 1.概念:给单独的一行记录加锁,主要应用于innodb表存储引擎 2.特点:在innodb存储引擎中应用比较多,支持事务.开销大.加锁慢:会出现死锁:锁的粒度小,并发情况下,产生锁 ...
- 华三IRF的配置
https://blog.csdn.net/VictoryKingLIU/article/details/79255901 拓扑结构 1 配置成员编号(重启) 2 配置成员优先级(大的主设备) 3 配 ...
- 【知了堂学习笔记】java IO流归纳总结
皮皮潇最近学到了IO流但是感觉这一块要记的东西太多了,所以重API上查阅并总结了以下几点关于IO的知识. 1.File(文件类): File类是文件以及文件夹进行封装的对象,用对象的思想来操作文件和文 ...
- 使用IDEA和Maven创建Javaweb项目
1.File -- New -- Project
- Linux-数据库4
存储引擎 什么是存储引擎? mysql中建的库是文件夹,建的表是文件.文件有不同的类型,数据库中的表也有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎. 存储引擎说白了 ...
- Ubuntu安装redis和redis-php扩展
通过apt-get安装的redis使用方法 sudo apt-get install redis-server sudo apt-get install php-redis vim /etc/redi ...
- hihocoder 1509 异或排序
题面在这里! 考虑前后两个数 x,y,可以发现S只有在(x xor y)的最高有1位上的取值是要被确定的 (如果x==y那么没有限制),可以推一下什么情况下是1/0. 于是我们模拟一下这个操作,判一判 ...
- BZOJ 3238 [Ahoi2013]差异(后缀自动机)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3238 [题目大意] 给出一个串,设T[i]表示从第i位开始的后缀, 求sum(len( ...
- [COGS2639]偏序++
[COGS2639]偏序++ 题目大意: \(n(n\le40000)\)个\(k(k\le7)\)元组,求\(k\)维偏序. 思路: 分块后用bitset维护. 时间复杂度\(\mathcal O( ...
- HTTPClient实现免登陆请求(带cookie请求)
背景: 使用httpClient请求某登录型网站,模拟一个操作,一般步骤一个httpclient模式登录->httpClient模拟操作: 此时发现,每次操作都需要进行一次登录,极其浪费时间,是 ...