C#深浅拷贝的深入解析_C#教程

来源:脚本之家  责任编辑:小易  

使用memcpy即可,比如你另外建立一个结构体sortbook[1000]用来保存排序结果,将book中的第i个元素赋值到sortbook的第j个元素中memcpy(&sortbook[j],&book[i],sizeof(struct book));用这个函数需要#include<string.h>www.zgxue.com防采集请勿采集本网。

前言

前面我们学习完了设计模式,在其中我们有了解到原型模式。这里涉及到了克隆自身对象。那么也就是对对象进行拷贝。这里就涉及到了这么一个概念。深浅拷贝、何为深拷贝何为浅拷贝呢?我们一起来看看吧。

解决方法如下: 它只是一个开源库,并不是一个单独的软件, 对于遥感来说,1W像素实在不算多。GDAL对你这个问题没有什么意义,因为GDAL是用来读写图像文件的,而你的问题是绘制。要绘制影像,以下几点要

浅拷贝

首先我们看看浅拷贝。浅拷贝就是将对象中的所有字段复制到新对象中去,浅拷贝对于值类型和引用类型有不同的影响。值类型的值被复制到副本中后,修改副本中的值不会影响原来对象的值。然而引用类型被复制到副本中的是引用类型的引用。不是引用的对象。这样再修改副本中的值是会导致原来对象的值也被修改了。但是这里引用类型情况我们需要排除字符串String类型。

.net程序编译时生成的是中间语言IL,IL是不能直接被硬件执行的,需要虚拟机层(对.net来说就是CLR)解析执行,解析是需要代价的,所以无论是.net的CLR还是java的jvm,都采用了即时编译技术,在运行

那么为何引用类型修改副本的值会造成原来对象的值的变化,而string字符串类型却排除在外呢?首先我们需要知道这么一个概念,string类型是一个不可变的数据类型,也就是意味着对字符串对象进行了初始化,该字符串对象就不能改变了。表面上我们修改字符串的内容的方法和运算实际上是创建了一个新字符串,然后根据需要可以把旧字符串的内容复制到新字符串中。怎么理解你?我们看下面这个案例:

行为层DLL的路径是在项目的Library/ScriptAssemblies下,有Assembly-CSharp.dll和Assembly-CSharp-firstpass.dll两个文件。另外也拷贝逻辑层依赖的其它DLL到构建目录,包括UnityEngine.dll,以及项目

#region 字符串比较 /// <summary> /// 获取引用类型的内存地址方法 /// </summary> /// <param name="o"></param> /// <returns></returns> public static string getMemory(object o) { GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned); IntPtr addr = h.AddrOfPinnedObject(); return "0x" + addr.ToString("X"); } /// <summary> /// 字符串比较 /// </summary> public static void Compares() { string a = "123"; Console.WriteLine("a的引用地址:\t\t" + getMemory(a)); string b = "123"; Console.WriteLine("b的引用地址:\t\t" + getMemory(b)); Console.WriteLine("a与b的比较:\t\t" + Object.ReferenceEquals(a, b)); b = "456"; Console.WriteLine("b的引用地址:\t\t" + getMemory(b)); } #endregion

运行结果: 12 34 5 41 思路: 保存最后一次的算符(lastOperator,+或-),保存上一次读入的数字(lastNumber)。如果当前算符operator的优先级低(+或-),更新数据(data=data+或-lastNumber) 如果当前

这里我们看a=”123”,b=”123”。我们看他们的引用地址是一样的。也就是说我们先创建a的时候创建了字符串a,有了一个引用地址。然后我们创建b的时候首先会寻找是否存在相同的值。如果存在相同的值就获取其引用地址。这也就是为什么a与b的引用地址是一样的。这里涉及到一个叫做字符驻留池的东西。会对字符串进行保存。那么后面我们修改b的值然后输出其引用地址,发现和之前的引用地址不一样。说明并不是修改原来的值,而是重新创建了一个字符串,重新获取了它的引用地址。

copy_loop:@copy 32 bytes at a time/开始拷贝 ldmia r0!{r3-r10}@copy from source address[r0] stmia r1!{r3-r10}@copy to target address[r1] cmp r0,r2@until source end addreee[r2] ble copy_loop

我们接下来看一个浅拷贝的案例吧,首先我们准备的是以下的数据类型的值:int,string,enum,struct,class,int[],string[]。

/// <summary> /// 枚举 /// </summary> public enum EnumTest { TestOne = 1, TestTwo = 2 } /// <summary> /// 结构体 /// </summary> public struct StructTest { public int Test; public StructTest(int i) { Test = i; } } /// <summary> /// 类 /// </summary> public class ClassTest { public string TestString; public ClassTest(string _string) { TestString = _string; } } /// <summary> /// 深拷贝 /// </summary> public class DeepClone : ICloneable { public int _int = 1; public string _string = "1"; public EnumTest _enum = EnumTest.TestOne; public StructTest _struct = new StructTest(1); public ClassTest _class = new ClassTest("1"); public int[] arrInt = new int[] { 1 }; public string[] arrString = new string[] { "1" }; public object Clone() { var NewOne = JsonConvert.SerializeObject(this); return JsonConvert.DeserializeObject<DeepClone>(NewOne); } } class Program { static void Main(string[] args) { DeepClone simple = new DeepClone(); var simpleTwo = (DeepClone)simple.Clone(); simpleTwo._int = 2; simpleTwo._string = "2"; simpleTwo._enum = EnumTest.TestTwo; simpleTwo._struct.Test = 2; simpleTwo._class.TestString = "2"; simpleTwo.arrInt[0] = 2; simpleTwo.arrString[0] = "2"; Console.WriteLine($"int 类型变化 原对象:{simple._int}\t\t 备份对象:{simpleTwo._int}"); Console.WriteLine($"string 类型变化 原对象:{simple._string}\t\t 备份对象:{simpleTwo._string}"); Console.WriteLine($"enum 类型变化 原对象:{(int)simple._enum}\t\t 备份对象:{(int)simpleTwo._enum}"); Console.WriteLine($"struct 类型变化 原对象:{simple._struct.Test}\t\t 备份对象:{simpleTwo._struct.Test}"); Console.WriteLine($"class 类型变化 原对象:{simple._class.TestString}\t\t 备份对象:{simpleTwo._class.TestString}"); Console.WriteLine($"int数组 类型变化 原对象:{simple.arrInt[0]}\t\t 备份对象:{simpleTwo.arrInt[0]}"); Console.WriteLine($"string数组 类型变化 原对象:{simple.arrString[0]}\t\t 备份对象:{simpleTwo.arrString[0]}"); } }

我们通过继承ICloneable接口对这些类型都进行了浅拷贝然后修改副本对象。输出原对象和副本对象进行比较。我们发现int,enum,struct、值类型以及string这个特殊的引用类型的原对象值没有被影响改变。但是class,int[],string[]这些引用类型对象原对象被影响改变了值。也就再次验证了我们前面说的。浅拷贝是将对象进行赋值到一个副本对象中去,值类型复制值,引用类型复制其引用对象。修改副本对象值,值类型和string原对象不会被影响改变,引用类型除string其原对象都会被影响改变。

深拷贝

我们上面看了浅拷贝,浅拷贝还是有一定的影响的,处理不好可能就成bug。那么我们看看对应的深拷贝又是什么样的呢?这里可以先声明,深拷贝对值类型和引用类型都没有区别对待。深拷贝也是将对象中的所有字段复制到新对象中去,但是对象无论是值类型还是引用类型都将被重新创建然后复制到副本对象去。对于副本对象的修改将不会影响到原对象,无论任何类型。

我们继续将上面的例子进行深拷贝看看:

/// <summary> /// 深拷贝 /// </summary> public class DeepClone : ICloneable { public int _int = 1; public string _string = "1"; public EnumTest _enum = EnumTest.TestOne; public StructTest _struct = new StructTest(1); public ClassTest _class = new ClassTest("1"); public int[] arrInt = new int[] { 1 }; public string[] arrString = new string[] { "1" }; public object Clone() { var NewOne = JsonConvert.SerializeObject(this); return JsonConvert.DeserializeObject<DeepClone>(NewOne); } } class Program { static void Main(string[] args) { DeepClone simple = new DeepClone(); var simpleTwo = (DeepClone)simple.Clone(); simpleTwo._int = 2; simpleTwo._string = "2"; simpleTwo._enum = EnumTest.TestTwo; simpleTwo._struct.Test = 2; simpleTwo._class.TestString = "2"; simpleTwo.arrInt[0] = 2; simpleTwo.arrString[0] = "2"; Console.WriteLine($"int 类型变化 原对象:{simple._int}\t\t 备份对象:{simpleTwo._int}"); Console.WriteLine($"string 类型变化 原对象:{simple._string}\t\t 备份对象:{simpleTwo._string}"); Console.WriteLine($"enum 类型变化 原对象:{(int)simple._enum}\t\t 备份对象:{(int)simpleTwo._enum}"); Console.WriteLine($"struct 类型变化 原对象:{simple._struct.Test}\t\t 备份对象:{simpleTwo._struct.Test}"); Console.WriteLine($"class 类型变化 原对象:{simple._class.TestString}\t\t 备份对象:{simpleTwo._class.TestString}"); Console.WriteLine($"int数组 类型变化 原对象:{simple.arrInt[0]}\t\t 备份对象:{simpleTwo.arrInt[0]}"); Console.WriteLine($"string数组 类型变化 原对象:{simple.arrString[0]}\t\t 备份对象:{simpleTwo.arrString[0]}"); } }

这里我们看这个运行结果,无论值类型还是引用类型修改副本对象之后都没有影响原对象的值。这也就是深拷贝的特点了。

总结

我们看完了浅拷贝与深拷贝,我们仔细回顾下。浅拷贝将对象的字段复制到新的对象中去,但是当修改新对象的时候,值类型和string类型的字段将不会影响原对象的字段,而引用类型除string类型外都将影响原对象的值。深拷贝也是将对象的字段复制到新的对象中去,但是无论是值类型还是引用类型的改变都不会影响原对象的值。因为深拷贝是将原对象重新创建然后复制到副本对象中去的。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对真格学网的支持。

你可以访问Python数据库接口及API查看详细的支持数据库列表。不同的数据库你需要下载不同的DBAPI模块,例如你需要访抄问Oracle数据库和Mysql数据,你需要下载Oracle和MySQL数据库模块。DB-API是一个规范.它定义了一系列必须的对象和数据库存取方式,以便为各种各样的底2113层数据库系统和多种多样的数据库接口程序提供一致的访问接口。Python的DB-API,为大多数的数据库实现了接口,5261使用它连接各数据库后,就可以用相同的方式操作各数据4102库。PythonDB-API使用流程:引入API模块。获取与数据库的连接。执行SQL语句和存储过程。关闭数1653据库连接。什么是MySQLdb?MySQLdb是用于Python链接Mysql数据库的接口,它实现了Python数据库API规范V2.0,基于MySQLCAPI上建立的。如何安装MySQLdb?为了用DB-API编写MySQL脚本,必须确保已经安装了MySQL。复制以下代码,并执行:#!usr/bin/python#-*-coding:UTF-8-*-importMySQLdb内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • c#浅拷贝和深拷贝实例解析
  • c# 深拷贝与浅拷贝的区别分析及实例
  • 简单谈谈c#中深拷贝、浅拷贝
  • c#中4种深拷贝方法介绍
  • c#中使用datacontractserializer类实现深拷贝操作示例
  • c#中序列化实现深拷贝,实现datagridview初始化刷新的方法
  • c#深拷贝文件夹示例
  • 一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)
  • c#爬虫爬取京东的商品信息
  • c#实现字符串首字母大写的方法示例
  • c#无损高质量压缩图片实现代码
  • 使用c#在注册表中保存信息的例子
  • c#编程获取资源文件中图片的方法
  • 简单实现winform编辑器
  • c#完美截断字符串代码(中文+非中文)
  • c#中使用iformattable实现自定义格式化字符串输出示例
  • c#实现简单学生信息管理系统
  • c#的dataset离线数据集示例
  • csharp怎么连接mysql数据库
  • c语言,结构体复制
  • c#解析JSON的几种办法
  • C#复制图文信息到剪切板再粘贴到word
  • C# GDAL 打开遥感影像图片
  • 解释一下 即时编译 ,,不要抄了,,谢谢 ^
  • 如何做Unity3d的代码混淆
  • 用C语言编写可以进行加减乘除整数运算混合运算的计算器,要求写思路,越详细越好,初学者,不要很复杂的。
  • android 源码里有u-boot吗
  • 求用c语言编写的贪吃蛇程序
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全c#教程vbvb.netc 语言java编程delphijavaandroidiosswiftscala易语言汇编语言其它相关首页c#浅拷贝和深拷贝实例解析c# 深拷贝与浅拷贝的区别分析及实例简单谈谈c#中深拷贝、浅拷贝c#中4种深拷贝方法介绍c#中使用datacontractserializer类实现深拷贝操作示例c#中序列化实现深拷贝,实现datagridview初始化刷新的方法c#深拷贝文件夹示例一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)c#爬虫爬取京东的商品信息c#实现字符串首字母大写的方法示例c#无损高质量压缩图片实现代码使用c#在注册表中保存信息的例子c#编程获取资源文件中图片的方法简单实现winform编辑器c#完美截断字符串代码(中文+非中文)c#中使用iformattable实现自定义格式化字符串输出示例c#实现简单学生信息管理系统c#的dataset离线数据集示例c#几种截取字符串的方法小结c#中httpwebrequest的用法详解c# datagridview添加新行的2个方c# 一个wcf简单实例c#中list〈string〉和string[]数c#连接mysql数据库的方法c#的dllimport使用方法详解c#中使用split分割字符串的几种方c#处理3种json数据的实例c#实现16进制和字符串之间转换的设计模式速记深入icomparable与icomparer的排序实例详c#调用百度api实现活体检测的方法c#很简单而又很经典的一句代码实例c#中的泛型委托详解c#中读写ini配置文件的方法winform界面中实现通用工具栏按钮的事件处c#日志记录帮助类分享c#的file类实现文件操作实例详解浅谈c#各种数组直接的数据复制/转换
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved