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. 【知了堂学习笔记】java web 简单的登录

    最近皮皮潇在学习java web,刚接触了简单的东西,所以今天给大家带来一个简单的登录实现. 页面: 页面代码: <%@ page language="java" conte ...

  2. JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

    1. 学习计划 1.Solr服务搭建 2.Solrj使用测试 3.把数据库中的数据导入索引库 4.搜索功能的实现 2. Solr服务搭建 2.1. Solr的环境 Solr是java开发. 需要安装j ...

  3. luogu4595 [COCI2011-2012#5] POPLOCAVANJE 后缀自动机

    看着就像后缀自动机.... 然后搜了一下,网上一大把的\(AC\)自动机 嗯...... 不管了,打一个试试 然后就过了\(QAQ\) 我们考虑对于每个点\(i\)求出它往前最长能匹配的子串的长度 可 ...

  4. [WC2014]时空穿梭(莫比乌斯反演)

    https://www.cnblogs.com/CQzhangyu/p/7891363.html 不难推到$\sum\limits_{D=1}^{m_1}\sum\limits_{d|D}C_{d-1 ...

  5. 【SPFA判断负环】BZOJ1715- [Usaco2006 Dec]Wormholes 虫洞

    [题目大意] 判断一张图中是否存在负环. [思路] dfs版SPFA. #include<bits/stdc++.h> using namespace std; struct edge { ...

  6. loj6300 「CodePlus 2018 3 月赛」博弈论与概率统计

    link 题意: A和B玩游戏,每轮A赢的概率为p.现在有T组询问,已知A赢了n轮输了m轮,没有平局,赢一局A得分+1,输一局得分-1,问A得分期望值? $n+m,T\leq 2.5\times 10 ...

  7. Linux下gcc与g++用法以及编写makefile

    1.         gcc与g++编译流程: 1)         编译流程: 2)         预处理:生成.i的预处理文件. Ø 只激活预处理,这个不生成文件,需要把它重定向一个输出文件. ...

  8. 鸟哥的私房菜:Linux磁盘与文件系统原理

    1 硬盘物理组成     //原理 磁头负责读写     磁道(硬盘同半径的一圈) 磁柱(所有盘磁道叠加起来的柱)     扇区(2条半径将磁道分开的一个扇形区域,是磁盘的最小存储单位) ------ ...

  9. MyBatis -- generator 逆向工程

    一.引言 官网文档:http://www.mybatis.org/generator/index.html 通过使用官方提供的mapper自动生成工具,mybatis-generator-core-1 ...

  10. SQLyog客户端无法连接MySQL服务器

    环境:centos下使用yum 命令安装了mysql服务 1.进入linux 通过命令service mysqld start启动mysql的服务 2.使用sqlyog 连接mysql发现连接不上,如 ...