OC内部:可变对象和不可变对象的深(复制)拷贝问题思考:

 
不可变对象:
 例如NSString对象,因为NSString对象是常量字符串,所以,不可以更改其内容,但是可以修改指向该字符串的指针指向。当对NSString对象做深拷贝时,如果是copy复制方式,其实就是浅复制,只是复制了同一个对象的指针;如果是mutableCopy复制方式,系统会分配一个新的内存空间用来存放复制出来的NSMutableString对象,此时地址是新的,内容是一样的,他们正在被不同的实例变量字符串指针指着。
 
可变对象:
  例如NSMutableString对象,因为NSMutableString对象是可变字符串,所以,可以改变其内容。当NSMutableString对象做深拷贝时,系统会分配一个新的内存空间用来存放复制出来的NSMutableString对象,此时地址是新的,内容是一样的,他们正在被不同的实例变量字符串指针指着。
 
总结:对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。
 
         如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的的。

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

主函数测试

  1. //  main.m
  2. //  测试
  3. //
  4. //  Created by ma c on 15/8/15.
  5. //  Copyright (c) 2015年. All rights reserved.
  6. //
  1. #import <Foundation/Foundation.h>
  2. #import "Person.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool
  6. {
  7. NSMutableString *name = [NSMutableString stringWithString:@"Jobs"];
  8. Person *p1 = [[Person alloc]initWithName:name];
  9. NSLog(@"%@----%p",name,p1.name);
  10. Person *p2 = [p1 copy];
  11. NSLog(@"%@----%p",name,p2.name);
  12. [name appendString:@"Tom"];
  13. Person *p3 = [[Person alloc]initWithName:name];
  14. NSLog(@"%@----%p",name,p3.name);
  15. Person *p4 = [p3 copy];
  16. NSLog(@"%@----%p",name,p4.name);
  17. }
  18. return 0;
  19. }

    测试结果如下:


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内部可变对象和不可变对象的深(复制)拷贝问题思考:的更多相关文章

  1. 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy

    读前小提示:对于深浅复制有一个清楚的了解,对于学习oc的朋友来说,至关重要.那么首先,我们要明白深浅复制是如何定义的呢.这里为了便于朋友们理解,定义如下. 浅 复 制:在复制操作时,对于被复制的对象的 ...

  2. Objective-C:MRC(引用计数器)在OC内部的可变对象是适用的,不可变对象是不适用的(例如 NSString、NSArray等)

    引用计数和字符串 内存中的常量字符串的空间分配与其他对象不同,他们没有引用计数机制 凡是自定义的对象都有引用计数机制: OC内部中对象分为可变对象(NSMutableString等)和不可变对象(NS ...

  3. Java基础知识强化101:Java 中的 String对象真的不可变吗 ?

    1. 什么是不可变对象?       众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...

  4. 区分Python中的可变对象和不可变对象

    参考: https://www.cnblogs.com/sun-haiyu/p/7096918.html """不过注意函数传参既不是传值也不是传引用,正确的叫法是传对象 ...

  5. python 中的可变对象与不可变对象

    近日辞职待工,没有实际的项目与大家分享.暂写写在实际运用python中遇到的关于可变对象和不可变对象的坑. 首先我们需要明确一个概念,在python中一且皆对象.我们一般定义一个变量a=0,其实质a是 ...

  6. String对象为什么不可变

    转载:https://www.cnblogs.com/leskang/p/6110631.html 一.什么是不可变对象? As we all know, 在Java中, String类对象是不可变的 ...

  7. Python中的不可变对象类型与可变对象类型

    https://blog.csdn.net/answer3lin/article/details/86430074 其实各个标准资料中没有说明Python有值类型和引用类型的分类,这个分类一般是C++ ...

  8. 【Python】可变对象和不可变对象

    Python在heap中分配的对象分成两类:可变对象和不可变对象.所谓可变对象是指,对象的内容是可变的,例如list.而不可变的对象则相反,表示其内容不可变. 不可变对象:int,string,flo ...

  9. Python 可变对象和不可变对象

    具体可以看这里:http://thomaschen2011.iteye.com/blog/1441254 不可变对象:int,string,float,tuple 可变对象   :list,dicti ...

随机推荐

  1. const理解

    const int * a4 = &a1; ///const data,non-const pointer int * const a5 = &a1; ///non-const dat ...

  2. mysql 判断两个字符串是否存在包含关系-------(1,2,3)与(2,3)

    1.这里这个是目前有问题的   #创建FUNCTION  DELIMITER ;     CREATE FUNCTION `is_mixed`(str1 TEXT, str2 TEXT) RETURN ...

  3. Java设计模式 - 持续更新

    注意,此博客来源于我的 OneNote 笔记本 因此属于图片形式进行展示,这意味着你可以: 不经过我的同意进行保存 不经过我的同意进行发布 我仍然希望搬运时留一个网址指明来处:我的博客园 多谢!以下是 ...

  4. Python 中的语句

    上一节已经了解到了Python中的基本数据类型和一些基本的操作,本节就大致讲一下关于Python中的语句的相关问题. 我们熟悉的print()语句可能是这样的.print('YJK923') or p ...

  5. 如何快速分析出现性能问题的Linux服务器

    Brendan Gregg曾经分享过当遇到一个系统性能问题时,如何利用登录的前60秒对系统的性能情况做一个快速浏览和分析,主要包括如下10个工具,这是一个非常有用且有效的工具列表.本文将详细介绍这些命 ...

  6. 1002 A+B for Polynomials (25)(25 point(s))

    problem 1002 A+B for Polynomials (25)(25 point(s)) This time, you are supposed to find A+B where A a ...

  7. socket--多进程,多线程服务器

    一:概念: 我们知道IP地址是标志网络中不用主机的IP地址,而端口号就是同一台主机上标志不同进程的地址,IP地址和端口号标志网络中的唯一地址.(又称socket) 在TCP协议中,建⽴立连接的两个进程 ...

  8. python opencv3 直线检测

    git:https://github.com/linyi0604/Computer-Vision # coding:utf8 import cv2 import numpy as np # 读入图像 ...

  9. LCD

    <LCD硬件体系结构> LCD控制器:位于ARM核内部,为LCD提供需要显示的数据,控制信息,控制时序 <LCD控制器结构> REGBANKK : 寄存器组,总共有17个寄存器 ...

  10. 【SPFA】POJ1860-Currency Exchange

    [题目大意] 给出每两种货币之间交换的手续费和汇率,求出从当前货币s开始交换,能否赚. [思路] 反向运用SPFA,判断是否有正环.每次队首元素出队之后,判断一下到源点s的距离是否增大,增大则返回tr ...