zoukankan      html  css  js  c++  java
  • 深拷贝和浅拷贝的区别

    浅拷贝一般是用的这个方法  MemberwiseClone()
    
    在拷贝的时候主要是关心值和引用两者拷贝后的区别,这个区别也是深拷贝和浅拷贝的区别
    
    
    下面这个类中就使用了这个方法
    
    
             class DemoClass : ICloneable
        {
            public int intValue = 1;
            public string strValue = "1";
            public PersonEnum pEnum = PersonEnum.EnumA;
            public PersonStruct pStruct = new PersonStruct();
            public Person pClass = new Person("1");
    
            public int[] pIntArray = new int[] { 1 };
            public string[] pArray = new string[] { "1" };
            #region ICloneable 成员
    
             public DemoClass()
            {
                pStruct.StructValue = 1;
            }
            public object Clone()
            {
               return this.MemberwiseClone();
            }
            #endregion
        }
    
        class Person
        {
            public string Name;
    
            public Person(string name)
            {
                Name = name;
            }
    
        }
        public enum PersonEnum
        {
            EnumA=1,
            EnumB=2
        }
        public struct PersonStruct
        {
          public  int StructValue;
        }

    说明:

    
    
    这里的示例,我用上了:
    int
    string
    int[]
    string[]
    enum
    struct
    class
    然后接下来会产生实例A和克隆实例B。
    接着改变B的值,看A的值会不会被改变。
    
    
    
    
    

    接下我们看main方法

     static void Main(string[] args)
            {
                Demo();
            }
            public static void Demo()
            {
                DemoClass A = new DemoClass();
                DemoClass B = (DemoClass)A.Clone();
                B.intValue = 2;
                Write(string.Format("        int->[A:{0}] [B:{1}]", A.intValue, B.intValue));
                B.strValue = "2";
                Write(string.Format("     string->[A:{0}] [B:{1}]", A.strValue, B.strValue));
                B.pEnum = PersonEnum.EnumB;
                Write(string.Format("       Enum->[A:{0}] [B:{1}]", (int)A.pEnum, (int)B.pEnum));
                B.pStruct.StructValue = 2;
                Write(string.Format("     struct->[A:{0}] [B:{1}]", A.pStruct.StructValue, B.pStruct.StructValue));
                B.pIntArray[0= 2;
                Write(string.Format("   intArray->[A:{0}] [B:{1}]", A.pIntArray[0], B.pIntArray[0]));
                B.pStringArray[0= "2";
                Write(string.Format("stringArray->[A:{0}] [B:{1}]", A.pStringArray[0], B.pStringArray[0]));
                B.pClass.Name = "2";
                Write(string.Format("      Class->[A:{0}] [B:{1}]", A.pClass.Name, B.pClass.Name));
                System.Console.Read();
            }
            static void Write(string msg)
            {
                System.Console.WriteLine(msg);
            }

    说明:

    我们通过改变B实例的值,然后打印出A和B的值看结果。

    打印结果如下:

    从最后输出的结果我们得知:

    对于内部的Class的对象和数组,会Copy地址一份。[从而改变B时,A也被改变了]
    而对于其它内置的int/string/Enum/struct/object类型,则进行值copy。

    最后,我试着百度寻找浅拷贝最原生的定义,浅搜了一下找不到,那这个定义,就留给读者解答一下了。

    接着,我顺手比较了一下浅拷贝和深拷贝的性能测试:

    先在DemoClass加入一个函数:

    public object CloneNew()
    {
       return new DemoClass();
    }

    接着我们写示例代码比较:

    ExpandedBlockStart.gif
            public static void Compare()
            {
                DemoClass baseClass = new DemoClass();

                DateTime start = DateTime.Now;
                for (int i = 0; i < 1000000; i++)
                {
                    DemoClass newClass = (DemoClass)baseClass.Clone();
                }
                TimeSpan ts = DateTime.Now - start;
                System.Console.WriteLine("浅拷贝:" + ts.Ticks);

                DateTime start2 = DateTime.Now;
                for (int j = 0; j < 1000000; j++)
                {
                    DemoClass newClass = (DemoClass)baseClass.CloneNew();
                }
                TimeSpan ts2 = DateTime.Now - start2;
                System.Console.WriteLine("深拷贝:" + ts2.Ticks);

               
                System.Console.Read();
            }

    最后得出结果:

    看来直接用浅拷贝性能还不如直接返回一个new的对象。
    同样的,用克隆返回object最后还得对类型转换进行一些开销,教人情何以堪!
     
     
     
  • 相关阅读:
    彻底清除Linux centos minerd木马 实战  跟redis的设置有关
    linux 弹出光驱失败
    teamviewer "TeamViewer Daemon is not running
    linux 如何查找io的进程
    网站开启https后加密协议始终是TLS1.0如何配置成TLS1.2?
    查看openssl的版本
    https单向认证和双向认证
    pem转换成der
    locate: can not open `/var/lib/mlocate/mlocate.db': No such file or directory
    mysql 有报错  ERROR! MySQL is not running, but lock file (/var/lock/subsys/mysql) exists
  • 原文地址:https://www.cnblogs.com/zhengwei-cq/p/9167708.html
Copyright © 2011-2022 走看看