-
对象复制
2016-05-25 10:53:49在Objective-C中,基本数据类型(例如int、float、BOOL等)的复制比较简单,都是会在内存中对需要复制的变量创建一个副本,而对象的复制有两种形式:浅复制和深复制。 浅复制:将原始对象的指针值复制到副本中,即...1.浅复制与深复制
在Objective-C中,基本数据类型(例如int、float、BOOL等)的复制比较简单,都是会在内存中对需要复制的变量创建一个副本,而对象的复制有两种形式:浅复制和深复制。
浅复制:将原始对象的指针值复制到副本中,即指针复制,原始对象和副本共享引用的数据,相当于创建了一个文件的快捷方式。
深复制:复制原始对象指针所引用的数据,并将其赋给副本对象,即内容复制,相当于创建了一份新的文件。
当为一个类的属性添加copy关键字时,那么对这个属性赋值时,就会执行深复制操作;当把属性关键字改为strong或者weak时,那么对这个属性赋值时,就会执行浅复制(只复制指针地址)。
2.可变对象复制与不可变对象复制
在Foundation框架中,常用的几个类,如NSString、NSArray以及NSDictionary都有其对应的可变子类。当对不同对象进行复制时,系统会采用不同的复制方式,有的采用浅复制,有的采用深复制,因此有必要提前了解对不同类型的对象进行复制时,是指针复制还是值复制。
在NSObject类中提供了两种复制的实例方法,copy和mutableCopy。当对象调用copy方法时,会返回NSCopying协议中的 copyWithZone: 方法的返回值,前提是对象在定义中遵守了NSCopying协议;当对象调用mutableCopy方法时,会返回NSCopying协议中的 mutableCopyWithZone: 方法的返回值,前提是对象在定义中遵守了NSCopying协议。
当对不同类型的对象分别使用copy和mutableCopy方法进行复制时,可能对应不同的复制类型(深复制或浅复制),这取决于类中 copyWithZone: 以及 mutableCopyWithZone: 方法的实现逻辑。
请记住以下结论:
(1)NSString类使用copy为浅复制(指针复制),使用mutableCopy为深复制;NSMutableString类使用copy或者mutableCopy均为深复制。
(2)NSArray类使用copy为浅复制,使用mutableCopy为深复制。另外,不论使用copy还是mutableCopy,容器内的对象都是浅复制。
(3)NSMutableArray类不论使用copy还是mutableCopy都为深复制,容器内的对象都是浅复制。
(4)NSDictionary类使用copy为浅复制,使用mutableCopy为深复制,容器内的对象都是浅复制。
(5)NSMutableDictionary类不论使用copy还是mutableCopy都为深复制,容器内的对象都是浅复制。
3.自定义对象的复制
在实际开发中,对于一些自定义的对象,有时也希望对其进行复制。对于自定义对象的复制,首先要保证在类的定义中遵守NSCopying协议,然后实现 copyWithZone: 方法。对于自定义对象的复制特性(浅复制或深复制),都取决于 copyWithZone: 方法中的实现情况,对于类中定义的属性也需要综合考虑其定义中有关内存管理的特性(strong/weak/copy/assign)。
(1)类的定义与复制
首先自定义ClassA类以及ClassB类,并在ClassB类中,添加4个属性,这4个属性分别使用了copy、strong、weak和assign关键字,如下所示。
为了实现对该类对象的复制,要求ClassB遵守NSCopying协议,同时在.m文件中实现 copyWithZone: 方法,在该方法中的实现逻辑决定了当调用copy方法时对该类对象进行复制所采取的方式(深复制或者浅复制)。
(2)浅复制该类对象
当仅仅需要对该对象进行浅复制时,可以在 copyWithZone: 方法中,直接返回要复制的对象即可。
在ClassB.m文件中,实现 copyWithZone: 方法。
(3)深复制该类对象
当需要对自定义对象深复制时,需要在 copyWithZone: 方法中调用alloc以及init方法,重新开辟一块新的内存空间。另外,对于属性的复制过程中,也需要考虑到属性自身的特性,例如:有copy特性的属性需要重新生成新的副本,strong以及weak只需要做指针复制即可。
在ClassB.m文件中,实现 copyWithZone: 方法。
(4)深复制与浅复制的代码验证
在main.m文件中,添加一个函数,用来复制ClassB的对象,代码如下所示。
当ClassB中的 copyWithZone: 方法中采用浅复制时,复制后得到的副本指向同一内存地址,即进行了指针复制,内容还是原来的内容。
当ClassB中的 copyWithZone: 方法中采用深复制时,可以看到复制得到的对象与原对象的地址不同,同时属性中包含copy关键字的属性在复制过程中也进行了深复制,而strong/weak特性的属性仅仅做了指针复制。
-
C# 对象复制 拷贝
2018-06-13 10:23:20在我们工作中经常会用到对象复制的情况,比如 A对象为原有对象,把A对象赋值给B对象,记录原有数据,然后对A对象开始操作改变值,接着想知道 A都改变了那些值 都会先这样写: A a = new A(); a.ID = 10; a.Name = ...在我们工作中经常会用到对象复制的情况,比如 A对象为原有对象,把A对象赋值给B对象,记录原有数据,然后对A对象开始操作改变值,接着想知道 A都改变了那些值
都会先这样写:A a = new A(); a.ID = 10; a.Name = "jacky"; A b = a; a.ID = 11; a.Name = "zhuovi";
然后 结果并不是我们想要的,a b 两对象的值都被改变了。
有两种对象克隆的方法:浅拷贝和深拷贝。浅拷贝只是复制引用,而不会复制引用的对象。深拷贝会复制引用的对象。
原始对象中的引用和浅拷贝对象中的同一个引用都指向同一个对象。而深拷贝的对象包含了对象的一切直接或间接的引用。
下边给出我经常用的两种方法
1.MemberWiseClone
MemberWiseClone是Object类的受保护方法,能够通过创建一个新对象,并把所有当前对象中的非静态域复制到新对象中,从而创建一 个浅拷贝。对于值类型的域,进行的是按位拷贝。对于引用类型的域,引用会被赋值而引用的对象则不会。因此,原始对象及其克隆都会引用同一个对象。注意,这种方法对派生类都是有效的,也就是说,你只需在基类中定义一次Clone方法。下面是一个简单的例子:public class A{ public int ID{get;set;} public string Name{get;set;} public A Clone(){ return this.MemberWiseClone() as A; } }
2.用反射进行克隆
直接上代码System.Reflection.PropertyInfo[] pA = A.GetType().GetProperties(); System.Reflection.PropertyInfo[] pB = A.GetType().GetProperties(); for (int i = 0; i < pA.Length; i++) { if(pB[i].CanWrite) pB[i].SetValue(this, pA[i].GetValue(A, null)); }
当前了 还有一种 就是手动赋值 这个就不在这里说了 大家都知道 。
-
对象复制和对象赋值的区别
2018-02-28 11:20:15复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的赋值过程中。类的复制构造函数原型通常如下: class_name(const class_name&); 它接受一个指向类对象的常量引用...1. 何时调用复制构造函数
复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的赋值过程中。类的复制构造函数原型通常如下:
class_name(const class_name&);
它接受一个指向类对象的常量引用作为参数。例如,String类的复制构造函数的原型如下:
String(const String&);
新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。这在很多情况下都可能发生,最常见的情况是将新对象显示地初始化为现有的对象。例如,假设motto是一个String对象,则下面4种声明都将调用复制构造函数:
String ditto(motto);
String metoo = motto;
String also = String(motto);
String *pString = new String(motto);
其中中间的2种声明可能会使用复制构造函数直接创建metto和also,也可能会使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给 metoo和also,这取决于具体的实现。最后一种声明使用motto初始化一个匿名对象,并将新对象的地址赋给pString指针。
2. 何时调用赋值构造函数
赋值构造函数是通过重载赋值操作符实现的,这种操作符的原型如下:
Class_name& Class_name::operator=(const Class_name&);
它接受并返回一个指向类对象的引用。例如,String 类的赋值操作符的原型如下:
String& String::operator=(const String&);
将已有的对象赋给另一个对象时,将使用重载的赋值操作符:
String headline1(“test”);
String knot;
knot = headline1;
初始化对象时,并不一定会使用赋值操作符:
String metoo = knot;
这里,metoo是一个新创建的对象,被初始化为knot的值,考试,大提示使用复制构造函数。不过,正如前面指出的,实现时也可能分两步来处理这条语句:使用复制构造函数创建一个临时对象,然后通过赋值将临时对象的值复制到新对象中。这就是说,初始化总是会调用复制构造函数,而使用=操作符时也可能调用赋值操作符
实例代码如下:
#include <iostream>
using namespace std;
class Test
{
public:
Test();
~Test();
Test(const Test& t);
Test& operator=(const Test& t);
private:
int t1;
};
Test::Test()
{
cout<<”调用构造函数”<<endl;
}
Test::~Test()
{
cout<<”调用析构函数”<<endl;
}
Test::Test(const Test& t)
{
cout<<”调用复制构造函数”<<endl;
}
Test& Test::operator =(const Test& t)
{
cout<<”调用赋值构造函数”<<endl;
t1 = t.t1;
return *this;
}
void main()
{
Test t1;
Test t2 = t1;
Test t3;
t3 = t1;
}
输出如下:
调用构造函数
调用复制构造函数
调用构造函数
调用赋值构造函数
调用析构函数
调用析构函数
调用析构函数同样是利用现有对象的值,生成/更新另一个对象的值。区别在于:复制构造函数是去完成对未初始化的存储区的初始化,而赋值操作符则是处理一个已经存在的对象。对一个对象赋值,当它一次出现时,它将调用复制构造函数,以后每次出现,都调用赋值操作符。
定义对象a,并用另一个对象b对a进行初始化时,
若没有复制构造函数时,那么编译器会自动生成一个
T b(1);//假设对象b已经初始化
T a(b);//初试化阶段,调用复制构造函数
T c = b;//虽然使用了“=”,但是初试化阶段,仍调用复制构造函数
T c = a; //因为对象c已经定义,所以此处调用赋值操作符重载函数。如果没有编译器会自动生成一个。</div>
-
Spring BeanUtils 的对象复制 copyProperties
2019-06-14 16:33:36 -
Android或java中对象复制
2019-06-27 17:51:37做项目过程中有需求用到对象复制内容, 在此随手记录一下. 为何要复制对象, 在此就不做细数, 下面简单说明文字+代码. 对象复制, 总体来将, 分为三种方法. 方法一: 用getter和setter挨个进行赋值, 这种方式简单, ... -
JS对象复制
2012-08-28 16:52:22在JavaScript很多人复制一个对象的时候都是直接用"=",因为大家都觉得脚本语言是没有指针、引用、地址之类的,所以直接用"="就可以把一个对象复制给另外一个对象,如下代码: 代码1: var i1 = 1; var i2 = i1;... -
对象复制性能对比(7种)
2020-07-07 16:01:09一,问题背景 以往我们做单体系统的时候,没有那么复杂的架构,出参,入参都非常简单,很多人都会直接用map来进行组装,...今天我们来聊聊,现有的对象复制,哪些性能最快 二,对象复制有哪些方式 1、apache的B. -
python对象复制
2019-01-08 05:15:50需求:你想复制一个对象.因为在Python中,无论你把对象做为参数传递,做为函数返回值,都是引用传递的.讨论:标准库中的copy模块提供了两个方法来实现拷贝.一个方法是copy,它返回和参数包含内容一样的对象. import ... -
从对象复制到ModelMapper:从对象到对象的映射库
2015-12-12 15:29:58首先要指出内存堆与栈的区别: 栈存取速度比堆快,栈只存储一些临时变量(所谓的临时变量要好好理解:例如中间变量)与...接着要说的就是对象复制了(它有浅复制与深复制两种) @Data public class Person { priva -
BeanUtils对象复制(深度拷贝)终极工具类
2018-10-03 21:45:48对象复制工具类,实现方法如下: 复制对象(深度拷贝) 复制集合(深度拷贝) 复制对象到指定类(深度拷贝) 复制集合到指定类(深度拷贝) POM <!-- 对象拷贝 --> <dependency> <groupId>uk... -
php5对象复制、clone、浅复制与深复制
2013-09-08 09:54:45对象复制的由来 为什么对象会有“复制”这个概念,这与PHP5中对象的传值方式是密切相关的,让我们看看下面这段简单的代码 PHP代码 * /** * * 电视机类 * */ * class Television ... -
jQuery对象复制
2019-02-26 15:22:38// 浅层复制(只复制顶层的非 object 元素) var newObject = jQuery.extend({}, oldObject); // 深层复制(一层一层往下复制直到最底层) var newObject = jQuery.extend(true, {}, oldObject); ... -
C#对象复制探讨
2009-07-26 15:31:00对象复制探讨对象复制的种类:1.构造复制函数;2.克隆方法;1. 构造复制函数(以下摘抄自MSDNhttp://msdn.microsoft.com/zh-cn/library/ms173116(VS.80).aspx)与有些语言不同,C# 不提供复制构造函数。如果您创建... -
类对象复制问题|类的临时对象|赋值重载函数
2015-05-22 15:42:30对象复制操作产生的系统开销很大,尤其是对象占用的内存是动态分配时。对象的复制是通过调用类复制构造函数完成的。赋值运算符涉及到对象的复制,有些情况可以避免对象复制的开销。 #include #include using ... -
JavaScript中的对象复制(Object Clone)
2018-09-21 14:17:57JavaScript中并没有直接提供对象复制(Object Clone)的方法。因此下面的代码中改变对象b的时候,也就改变了对象a。 a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制... -
对象复制和赋值
2018-09-30 23:21:50赋值的过程是将一个对象的数据成员在存储空间的状态复制给另一个对象的数据成员的存 储空间。box2=box1;(前边没有类名) 2.类的数据成员中不可包括动态分配的数据,否则在赋值时可能出现严重的后果。 对象的复制... -
Java之Map对象复制小例子
2016-08-11 21:45:08Java之Map对象复制小例子 标签: java 2016-05-19 22:34 73人阅读 评论(0) 收藏 举报 分类: 一步一步学Java(23) 版权声明:本文为博主原创文章,未经博主允许不得转载。 ... -
C#类型基础----对象复制
2016-01-03 19:17:24C#类型基础----对象复制 前言 有的时候,创建一个对象可能会非常耗时,比如对象需要从远程数据库中获取数据来填充,又或者创建对象需要读取磁盘文件.此时,如果已经有了一个对象,再创建新对象时,可能会采用复制... -
visio 对象复制到其他程序
2011-04-12 22:20:00viso 对象复制到其他程序 -
js对象复制
2012-03-29 13:34:27在js里没有类似JAVA的clone方法,无法实现对对象的克隆,一般使用等号操作符来传递对象,但这样就造成了指针关联问题,修改任何一个对象,其关 联的对象也会被改变,但很多时候我们只想得到一个对象的拷贝,而非引用... -
BeanCopier对象复制学习
2017-04-11 10:55:14BeanCopier是Cglib包中的一个类,用于对象的复制。 注意:目标对象必须先实例化 而且对象必须要有setter方法 初始化例子: BeanCopier copier = BeanCopier.create(Source.class, Target.class, false); ... -
Java对象复制和数组复制(拷贝)
2017-10-05 02:52:23浅拷贝:只复制一个对象,对象内部存在的指向其他对象数组或者引用则不复制 深拷贝:对象,对象内部的引用均复制 对象拷贝 一、对象浅拷贝 Object类里的clone方法是浅复制 1. 实现Cloneable接口,该接口没有任何... -
js 对象复制 对象原型操作 把一个对象A赋值给另一个对象B 并且对象B 修改 不会影响 A对象
2018-06-04 11:11:10当我们在项目需要 复制一个对象到另一个对象并且 被复制的对象不能受复制后的对象的影响。我先总结下 我们哪些方法可以复制对象1234567891011121314151617181920212223// 直接赋值 var obj1 = { a: 1 };var obj2... -
java 对象复制 集合复制工具类
2019-09-29 10:44:52* 将源POJO对象数据复制给目标POJO对象的同名属性 * * @date 2018年12月4日 * @version 1.0 * * @param source 源 * @param target 目标 * @param * @param * @return 目标 */ public static , T> T ... -
深入讨论PHP5对象复制技术
2012-05-22 17:08:37对象复制的由来 为什么对象会有“复制”这个概念,这与PHP5中对象的传值方式是密切相关的,让我们看看下面这段简单的代码 PHP代码 /** * 电视机类 */ class Television { // 屏幕高度 protected $_screenLength... -
list对象复制问题
2017-04-10 10:25:47Java中的List.addAll复制对象 测试代码 import java.util.ArrayList; import java.util.List; /** * @author yannis * @date create time:2016年10月31日 上午11:10:31 * @version 1.0 * @parameter ... -
Unity对象复制赋值给同类型的对象(克隆对象)
2018-09-26 11:43:55当你想把对象的某一个属性更改后再添加到一个列表的时候,就会被最后的对象替换掉,就不能实现新对象的添加。下面两种方式可以实现对象赋值给同类型的对象,这两个对象的堆栈信息是不一样的。 方法一: 必须对对象...
-
MySQL 索引
-
文件操作基本流程
-
2021-03-04
-
MySQL 触发器
-
【优化求解】基于matlab粒子群算法的多目标优化【含Matlab源码 441期】
-
php 打印函数(echo , print, printf, print_f, var_dump)
-
curselib:curselib-源码
-
VMware vSphere ESXi 7 精讲/VCSA/VSAN
-
零基础极简以太坊智能合约开发环境搭建并开发部署
-
xx公安局讲忠诚严纪律立政德专题警示教育心得体会_仅供参考.pdf
-
【车间调度】基于matlab遗传算法多目标流水车间调度【含Matlab源码 443期】
-
用Go语言来写区块链(一)
-
MySQL 数据库权限管理(用户高级管理和精确访问控制)
-
PTA团体程序设计天梯赛-L2-032 彩虹瓶
-
MySQL 函数、用户自定义函数
-
NFS 实现高可用(DRBD + heartbeat)
-
SpringCloud小结
-
Twice_Bot-源码
-
最新wifidog认证服务器源码.zip
-
FP7195應用說明書V06.pdf