精华内容
下载资源
问答
  • js考虑最完善的深拷贝函数,可以深拷贝引用对象和基本对象
  • 利用线程池实现拷贝目录的效果,让其效果等同于cp命令。
  • C++之深拷贝和浅拷贝

    2015-09-09 19:06:07
    通过简短的代码和图片来说明C++中深拷贝和浅拷贝的区别和概念。
  • 任何变成语言中,其实都有浅拷贝和深拷贝的概念,Java 中也不例外。在对一个现有的对象进行拷贝操作的时候,是有浅拷贝和深拷贝之分的,他们在实际使用中,区别很大,如果对其进行混淆,可能会引发一些难以排查的...

    写在前面

    如果觉得有所帮助,记得点个关注和点个赞哦,非常感谢支持。
    任何变成语言中,其实都有浅拷贝和深拷贝的概念,Java 中也不例外。在对一个现有的对象进行拷贝操作的时候,是有浅拷贝和深拷贝之分的,他们在实际使用中,区别很大,如果对其进行混淆,可能会引发一些难以排查的问题。Java 中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、用作方法参数或返回值时,会有值传递和引用(地址)传递的差别。

    什么是浅拷贝和深拷贝

    首先需要明白,浅拷贝和深拷贝都是针对一个已有对象的操作。那先来看看浅拷贝和深拷贝的概念。上面讲了,在 Java 中,除了基本数据类型(元类型)之外,还存在类的实例对象这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。

    而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对是基本数据类型的对象属性进行了拷贝,而对是引用数据类型的对象属性,只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对是引用数据类型的对象属性进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。这段话要仔细理解清楚,如果我们对象直接用“=”赋值,那么只是对象拷贝,不交浅拷贝和深拷贝。所以就应该了解了,所谓的浅拷贝和深拷贝,只是在拷贝对象的时候,针对对象所拥有的属性拷贝的说法,而且一定是使用了clone才算是浅拷贝和深拷贝(下面讲解代码的时候还会进行说明)。

    • 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。
      在这里插入图片描述
    • 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
      在这里插入图片描述

    Java 中的拷贝

    对象拷贝

    • 我们所知道的直接赋值,即使用“=”,对于基本数据类型而言,都是进行值传递;
    • 对于对象进行直接赋值,即使用“=”,都是引用传递

    浅拷贝特点

    • 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个。
    • 对于引用类型的成员对象,比如数组或者类对象,因为引用类型是引用传递,所以浅拷贝只是把内存地址赋值给了成员变量,它们指向了同一内存空间。改变其中一个,会对另外一个也产生影响。

    深拷贝特点

    • 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个(和浅拷贝一样)。
    • 对于引用类型的成员对象,比如数组或者类对象,深拷贝会新建一个对象空间,然后拷贝里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
    • 对于有多层对象的成员对象,每个对象都需要实现 Cloneable 并重写 clone() 方法,进而实现了对象的串行层层拷贝。
    • 深拷贝相比于浅拷贝速度较慢并且花销较大。

    通过代码实现进一步理解

    上面的概念讲解还不理解的话,不要着急,这里我们使用代码来进行认识和思考,首先我们先要创建两个类,来为后面的讲解做准备,两个类分别是SubjectStudent,代码如下

    public class Student {
        private Subject subject;
        private String name;
        private int age;
    
        public Subject getSubject() {
            return subject;
        }
    
        public void setSubject(Subject subject) {
            this.subject = subject;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
        
    
        @Override
        public String toString() {
            return "[Student: " + this.hashCode() + ",subject:" + subject + ",name:" + name + ",age:" + age + "]";
        }
    }
    
    
    public class Subject {
    
        private String name;
    
        public Subject(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "[Subject: " + this.hashCode() + ",name:" + name + "]";
        }
    }
    
    

    直接赋值

    有了上面的代码之后呢,我们可以来体验一下直接赋值,我们知道,直接赋值对于基本数据类型而言,就是值传递,对于引用类型而言就是引用传递,比如,我们直接如下这样

    public class Main {
        public static void main(String[] args) {
            Subject subjectA = new Subject("hahah");
    
            Student studentA = new Student();
            studentA.setAge(18);
            studentA.setName("qqqqq");
            studentA.setSubject(subjectA);
    
            //直接赋值,不使用clone进行深浅拷贝
            Student studentB = studentA;
            studentA.setAge(20);
            System.out.println(studentA);
            System.out.println(studentB);
        }
    }
    

    在这里插入图片描述
    我们看到输出结果,发现哈希码都是一样的,说明 studentAstudentB 是指向了同一个对象,所以在更改age属性的时候,同时修改了。

    浅拷贝

    上面的操作叫做对象拷贝,那么我们接下来开始讲讲浅拷贝的代码,在讲解浅拷贝的代码之前,我们需要把Student类进行改造一下,让它实现Cloneable接口,并重写clone方法,Student改写之后代码如下

    public class Student implements Cloneable {
        private Subject subject;
        private String name;
        private int age;
    
        public Subject getSubject() {
            return subject;
        }
    
        public void setSubject(Subject subject) {
            this.subject = subject;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            //浅拷贝,直接调用父类的clone()方法
            return super.clone();
        }
    
        @Override
        public String toString() {
            return "[Student: " + this.hashCode() + ",subject:" + subject + ",name:" + name + ",age:" + age + "]";
        }
    }
    
    

    这个时候,我们就可以调用Studentclone方法,来完成对象的浅拷贝,我们只需要在上面的Main方法中,讲直接赋值的对象拷贝,改成clone的拷贝赋值就可以了

    public class Main {
        public static void main(String[] args) {
            Subject subjectA = new Subject("hahah");
    
            Student studentA = new Student();
            studentA.setAge(18);
            studentA.setName("qqqqq");
            studentA.setSubject(subjectA);
    
            //浅拷贝,使用clone进行浅拷贝
            Student studentB = null;
            try {
                studentB = (Student)studentA.clone();
            }catch (CloneNotSupportedException e){
                e.printStackTrace();
            }
            studentA.setAge(20);
            studentA.getSubject().setName("heihei");
            System.out.println(studentA);
            System.out.println(studentB);
        }
    }
    

    在这里插入图片描述
    我们看到输出结果,发现哈希码不一样的,说明 studentAstudentB 不是指向了同一个对象,所以在studentA更改age属性的时候,只有studentA修改了。但是在修改studentA的subject的时候,发现了没有,两个同时修改了,studentA和studentB两个的subject属性的哈希码是一样的,所以这也就是浅拷贝,浅拷贝对于对象的基本类型属性,是值传递,而对于引用类型的属性,是引用传递。

    深拷贝

    上面的操作叫做浅拷贝,那么我们接下来开始讲讲深拷贝的代码,在讲解深拷贝的代码之前,我们需要接着把Student类的clone方法进行改造一下,不仅如此,我们还需要把Subject类改造,让它实现Cloneable接口,重写clone方法,代码如下

    public class Subject implements Cloneable {
    
        private String name;
    
        public Subject(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        @Override
        public String toString() {
            return "[Subject: " + this.hashCode() + ",name:" + name + "]";
        }
    }
    
    
    public class Student implements Cloneable {
        //引用类型
        private Subject subject;
        //基础数据类型
        private String name;
        private int age;
    
        public Subject getSubject() {
            return subject;
        }
    
        public void setSubject(Subject subject) {
            this.subject = subject;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            //浅拷贝,直接调用父类的clone()方法
            Student student = (Student) super.clone();
            student.subject = (Subject) subject.clone();
            return student;
        }
    
        @Override
        public String toString() {
            return "[Student: " + this.hashCode() + ",subject:" + subject + ",name:" + name + ",age:" + age + "]";
        }
    }
    
    

    发现了没有,要想进行深拷贝,我们必须把拷贝对象里面的,所有引用类型属性的对象,都实现Cloneable接口,一层一层的属性对象,只要是引用类型的对象,都要实现Cloneable接口,这样才能实现深拷贝,我们接着使用上面浅拷贝的Main方法来检测一下深拷贝的结果

    public class Main {
        public static void main(String[] args) {
            Subject subjectA = new Subject("hahah");
    
            Student studentA = new Student();
            studentA.setAge(18);
            studentA.setName("qqqqq");
            studentA.setSubject(subjectA);
    
            //深拷贝,使用clone进行深拷贝
            Student studentB = null;
            try {
                studentB = (Student)studentA.clone();
            }catch (CloneNotSupportedException e){
                e.printStackTrace();
            }
            studentA.setAge(20);
            studentA.getSubject().setName("heihei");
            System.out.println(studentA);
            System.out.println(studentB);
        }
    }
    

    在这里插入图片描述
    由输出结果可见,深拷贝后,不管是基础数据类型还是引用类型的成员变量,修改其值都不会相互造成影响。

    通过序列化实现深拷贝

    也可以通过序列化来实现深拷贝。序列化是干什么的?它将整个对象图写入到一个持久化存储文件中并且当需要的时候把它读取回来, 这意味着当你需要把它读取回来时你需要整个对象图的一个拷贝。这就是当你深拷贝一个对象时真正需要的东西。请注意,当你通过序列化进行深拷贝时,必须确保对象图中所有类都是可序列化的。首先我们先对StudentSubject进行改造,这两个类都要实现Serializable接口,代码如下:

    import java.io.Serializable;
    
    public class Student implements Serializable {
        //引用类型
        private Subject subject;
        //基础数据类型
        private String name;
        private int age;
    
        public Subject getSubject() {
            return subject;
        }
    
        public void setSubject(Subject subject) {
            this.subject = subject;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "[Student: " + this.hashCode() + ",subject:" + subject + ",name:" + name + ",age:" + age + "]";
        }
    }
    
    
    import java.io.Serializable;
    
    public class Subject implements Serializable {
    
        private String name;
    
        public Subject(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "[Subject: " + this.hashCode() + ",name:" + name + "]";
        }
    }
    
    

    我们完成了这两个类的改造之后呢,我们接下来在Main方法中测试他们,Main方法的内容如下:

    public class Main {
        public static void main(String[] args) throws Exception {
            Subject subjectA = new Subject("hahah");
    
            Student studentA = new Student();
            studentA.setAge(18);
            studentA.setName("qqqqq");
            studentA.setSubject(subjectA);
    
            // 通过序列化实现深拷贝
            ObjectOutputStream objectOutputStream = null;
            ObjectInputStream objectInputStream = null;
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(outputStream);
            // 序列化以及传递这个对象
            objectOutputStream.writeObject(studentA);
            objectOutputStream.flush();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            objectInputStream = new ObjectInputStream(inputStream);
            // 返回新的对象
            Student studentB = (Student)objectInputStream.readObject();
    
            studentB.setAge(20);
            studentB.setName("wwwww");
            studentB.getSubject().setName("heihei");
            System.out.println(studentA);
            System.out.println(studentB);
        }
    }
    

    在这里插入图片描述

    延迟拷贝

    延迟拷贝是浅拷贝和深拷贝的一个组合,实际上很少会使用。 当最开始拷贝一个对象时,会使用速度较快的浅拷贝,还会使用一个计数器来记录有多少对象共享这个数据。当程序想要修改原始的对象时,它会决定数据是否被共享(通过检查计数器)并根据需要进行深拷贝。延迟拷贝从外面看起来就是深拷贝,但是只要有可能它就会利用浅拷贝的速度。当原始对象中的引用不经常改变的时候可以使用延迟拷贝。由于存在计数器,效率下降很高,但只是常量级的开销。而且,在某些情况下,循环引用会导致一些问题。

    总结

    如果对象的属性全是基本类型的,那么可以使用浅拷贝,但是如果对象有引用属性,那就要基于具体的需求来选择浅拷贝还是深拷贝。我的意思是如果对象引用任何时候都不会被改变,那么没必要使用深拷贝,只需要使用浅拷贝就行了。如果对象引用经常改变,那么就要使用深拷贝。没有一成不变的规则,一切都取决于具体需求。

    展开全文
  • 一文了解Python深拷贝与浅拷贝问题

    千次阅读 多人点赞 2019-03-01 12:36:29
    在平时工作中,经常涉及到数据的传递,在数据传递使用过程中,可能会发生数据被修改的问题。...今天就说一下Python中的深拷贝与浅拷贝的问题。 概念普及:对象、可变类型、引用 数据拷贝会涉...

    https://www.toutiao.com/a6661446735224635907/

     

    在平时工作中,经常涉及到数据的传递,在数据传递使用过程中,可能会发生数据被修改的问题。为了防止数据被修改,就需要在传递一个副本,即使副本被修改,也不会影响原数据的使用。为了生成这个副本,就产生了拷贝。今天就说一下Python中的深拷贝与浅拷贝的问题。

    概念普及:对象、可变类型、引用

    数据拷贝会涉及到Python中对象、可变类型、引用这3个概念,先来看看这几个概念,只有明白了他们才能更好的理解深拷贝与浅拷贝到底是怎么一回事。

    Python对象

    在Python中,对对象有一种很通俗的说法,万物皆对象。说的就是构造的任何数据类型都是一个对象,无论是数字,字符串,还是函数,甚至是模块,Python都对当做对象处理。

    所有Python对象都拥有三个属性:身份、类型、值。

    看一个简单的例子:

    In [1]: name = "laowang" # name对象
    In [2]: id(name) # id:身份的唯一标识
    Out[2]: 1698668550104
    In [3]: type(name) # type:对象的类型,决定了该对象可以保存什么类型的值
    Out[3]: str
    In [4]: name # 对象的值,表示的数据
    Out[4]: 'laowang'
    

    可变与不可变对象

    在Python中,按更新对象的方式,可以将对象分为2大类:可变对象与不可变对象。

    • 可变对象: 列表、字典、集合
    • 所谓可变是指可变对象的值可变,身份是不变的。
    • 不可变对象:数字、字符串、元组
    • 不可变对象就是对象的身份和值都不可变。新创建的对象被关联到原来的变量名,旧对象被丢弃,垃圾回收器会在适当的时机回收这些对象。
    In [7]: var1 = "python"
    In [8]: id(var1)
    Out[8]: 1700782038408
    #由于var1是不可变的,重新创建了java对象,随之id改变,旧对象python会在某个时刻被回收
    In [9]: var1 = "java"
    In [10]: id(var1) 
    Out[10]: 1700767578296
    

    引用

    在 Python 程序中,每个对象都会在内存中申请开辟一块空间来保存该对象,该对象在内存中所在位置的地址被称为引用。在开发程序时,所定义的变量名实际就对象的地址引用。

    引用实际就是内存中的一个数字地址编号,在使用对象时,只要知道这个对象的地址,就可以操作这个对象,但是因为这个数字地址不方便在开发时使用和记忆,所以使用变量名的形式来代替对象的数字地址。 在 Python 中,变量就是地址的一种表示形式,并不开辟开辟存储空间。

    就像 IP 地址,在访问网站时,实际都是通过 IP 地址来确定主机,而 IP 地址不方便记忆,所以使用域名来代替 IP 地址,在使用域名访问网站时,域名被解析成 IP 地址来使用。

    通过一个例子来说明变量和变量指向的引用就是一个东西

    In [11]: age = 18
    In [12]: id(age)
    Out[12]: 1730306752
    In [13]: id(18)
    Out[13]: 1730306752
    

    逐步深入:引用赋值

    上边已经明白,引用就是对象在内存中的数字地址编号,变量就是方便对引用的表示而出现的,变量指向的就是此引用。赋值的本质就是让多个变量同时引用同一个对象的地址。 那么在对数据修改时会发生什么问题呢?

    • 不可变对象的引用赋值
    • 对不可变对象赋值,实际就是在内存中开辟一片空间指向新的对象,原不可变对象不会被修改。
    • 原理图如下:

    一文了解Python深拷贝与浅拷贝问题

     

    下面通过案例来理解一下:

    a与b在内存中都是指向1的引用,所以a、b的引用是相同的

    In [1]: a = 1
    In [2]: b = a
    In [3]: id(a)
    Out[3]: 1730306496
    In [4]: id(b)
    Out[4]: 1730306496
    

    现在再给a重新赋值,看看会发生什么变化?

    从下面不难看出:当给a 赋新的对象时,将指向现在的引用,不在指向旧的对象引用。

    In [1]: a = 1
    In [2]: b = a
    In [5]: a = 2
    In [6]: id(a)
    Out[6]: 1730306816
    In [7]: id(b)
    Out[7]: 1730306496
    
    • 可变对象的引用赋值
    • 可变对象保存的并不是真正的对象数据,而是对象的引用。当对可变对象进行赋值时,只是将可变对象中保存的引用指向了新的对象。

    原理图如下:

    一文了解Python深拷贝与浅拷贝问题

     

    仍然通过一个实例来体会一下,可变对象引用赋值的过程。

    当改变l1时,整个列表的引用会指新的对象,但是l1与l2都是指向保存的同一个列表的引用,所以引用地址不会变。

    In [3]: l1 = [1, 2, 3]
    In [4]: l2 = l1
    In [5]: id(l1)
    Out[5]: 1916633584008
    In [6]: id(l2)
    Out[6]: 1916633584008
    In [7]: l1[0] = 11
    In [8]: id(l1)
    Out[8]: 1916633584008
    In [9]: id(l2)
    Out[9]: 1916633584008
    

    主旨详解:浅拷贝、深拷贝

    经过前2部分的解读,大家对对象的引用赋值应该有了一个清晰的认识了。

    下面大家思考一个这样的问题:Python中如何解决原始数据在函数传递之后不受影响了?

    这个问题Python已经帮我们解决了,使用对象的拷贝或者深拷贝就可以愉快的解决了。

    下面具体来看看Python中的浅拷贝与深拷贝是如何实现的。

    • 浅拷贝:

    为了解决函数传递后被修改的问题,就需要拷贝一份副本,将副本传递给函数使用,就算是副本被修改,也不会影响原始数据 。

    不可变对象的拷贝

    不可变对象只在修改的时候才会在内存中开辟新的空间, 而拷贝实际上是让多个对象同时指向一个引用,和对象的赋值没区别。

    同样的,通过一个实例来感受一下:不难看出,a与b指向相同的引用,不可变对象的拷贝就是对象赋值。

    In [11]: import copy
    In [12]: a = 10
    In [13]: b = copy.copy(a)
    In [14]: id(a)
    Out[14]: 1730306496
    In [15]: id(b)
    Out[15]: 1730306496
    

    可变对象的拷贝

    对于不可变对象的拷贝,对象的引用并没有发生变化,那么可变对象的拷贝会不会和不可变对象一样了?我们接着往下看。

    通过下面这个实例可以看出:可变对象的拷贝,会在内存中开辟一个新的空间来保存拷贝的数据。当再改变之前的对象时,对拷贝之后的对象没有任何影响。

    In [24]: import copy
    In [25]: l1 = [1, 2, 3]
    In [26]: l2 = copy.copy(l1)
    In [27]: id(l1)
    Out[27]: 1916631742088
    In [28]: id(l2)
    Out[28]: 1916636282952
    In [29]: l1[0] = 11
    In [30]: id(l1)
    Out[30]: 1916631742088
    In [31]: id(l2)
    Out[31]: 1916636282952
    

    原理图如下:

    一文了解Python深拷贝与浅拷贝问题

     

    现在再回到刚才那个问题,是不是浅拷贝就可以解决原始数据在函数传递之后不变的问题了?下面看一个稍微复杂一点的数据结构。

    通过下面这个实例可以发现:复杂对象在拷贝时,并没有解决数据在传递之后,数据改变的问题。 出现这种原因,是copy() 函数在拷贝对象时,只是将指定对象中的所有引用拷贝了一份,如果这些引用当中包含了一个可变对象的话,那么数据还是会被改变。 这种拷贝方式,称为浅拷贝。

    In [35]: a = [1, 2]
    In [36]: l1 = [3, 4, a]
    In [37]: l2 = copy.copy(l1)
    In [38]: id(l1)
    Out[38]: 1916631704520
    In [39]: id(l2)
    Out[39]: 1916631713736
    In [40]: a[0] = 11
    In [41]: id(l1)
    Out[41]: 1916631704520
    In [42]: id(l2)
    Out[42]: 1916631713736
    In [43]: l1
    Out[43]: [3, 4, [11, 2]]
    In [44]: l2
    Out[44]: [3, 4, [11, 2]]
    

    原理图如下:

    一文了解Python深拷贝与浅拷贝问题

     

    对于上边这种状况,Python还提供了另一种拷贝方式(深拷贝)来解决。

    • 深拷贝

    区别于浅拷贝只拷贝顶层引用,深拷贝会逐层进行拷贝,直到拷贝的所有引用都是不可变引用为止。

    接下来我们看看,要是将上边的拷贝实例用使用深拷贝的话,原始数据改变的问题还会不会存在了?

    下面的实例清楚的告诉我们:之前的问题就可以完美解决了。

    import copy
    l1 = [3, 4, a]
    In [47]: l2 = copy.deepcopy(li)
    In [48]: id(l1)
    Out[48]: 1916632194312
    In [49]: id(l2)
    Out[49]: 1916634281416
    In [50]: a[0] = 11
    In [51]: id(l1)
    Out[51]: 1916632194312
    In [52]: id(l2)
    Out[52]: 1916634281416
    In [54]: l1
    Out[54]: [3, 4, [11, 2]]
    In [55]: l2
    Out[55]: [1, 2, 3]
    

    原理图如下:

    一文了解Python深拷贝与浅拷贝问题

     

    查漏补缺

    为什么Python默认的拷贝方式是浅拷贝?

    • 时间角度:浅拷贝花费时间更少
    • 空间角度:浅拷贝花费内存更少
    • 效率角度:浅拷贝只拷贝顶层数据,一般情况下比深拷贝效率高。

    本文知识点总结:

    • 不可变对象在赋值时会开辟新空间
    • 可变对象在赋值时,修改一个的值,另一个也会发生改变
    • 深、浅拷贝对不可变对象拷贝时,不开辟新空间,相当于赋值操作
    • 浅拷贝在拷贝时,只拷贝第一层中的引用,如果元素是可变对象,并且被修改,那么拷贝的对象也会发生变化
    • 深拷贝在拷贝时,会逐层进行拷贝,直到所有的引用都是不可变对象为止。
    • Python 中有多种方式实现浅拷贝,copy模块的copy 函数 ,对象的 copy 函数 ,工厂方法,切片等。
    • 大多数情况下,编写程序时,都是使用浅拷贝,除非有特定的需求
    • 浅拷贝的优点:拷贝速度快,占用空间少,拷贝效率高
    展开全文
  • Java深入理解深拷贝和浅拷贝区别

    万次阅读 多人点赞 2019-02-13 23:31:47
    一、拷贝的引入 (1)、引用拷贝 创建一个指向对象的引用变量的拷贝。 Teacher teacher = new Teacher("Taylor",26); Teacher otherteacher = teacher; System.out.println(teacher); System.out.println...

    欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。

    一、拷贝的引入

    (1)、引用拷贝

    创建一个指向对象的引用变量的拷贝。

    public class QuoteCopy {
        public static void main(String[] args) {
            Teacher teacher = new Teacher("riemann", 28);
            Teacher otherTeacher = teacher;
            System.out.println(teacher);
            System.out.println(otherTeacher);
        }
    }
    
    class Teacher {
        private String name;
        private int age;
    
        public Teacher(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    

    输出结果:

    com.test.Teacher@28a418fc
    com.test.Teacher@28a418fc
    

    结果分析:由输出结果可以看出,它们的地址值是相同的,那么它们肯定是同一个对象。teacherotherTeacher只是引用而已,他们都指向了一个相同的对象Teacher(“riemann”,28)。 这就叫做引用拷贝

    在这里插入图片描述

    (2)、对象拷贝

    创建对象本身的一个副本。

    public class ObjectCopy {
        public static void main(String[] args) throws CloneNotSupportedException {
            Teacher teacher = new Teacher("riemann", 28);
            Teacher otherTeacher = (Teacher) teacher.clone();
            System.out.println(teacher);
            System.out.println(otherTeacher);
        }
    }
    
    class Teacher implements Cloneable {
        private String name;
        private int age;
    
        public Teacher(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Object clone() throws CloneNotSupportedException {
            Object object = super.clone();
            return object;
        }
    }
    

    输出结果:

    com.test.Teacher@28a418fc
    com.test.Teacher@5305068a
    

    结果分析:由输出结果可以看出,它们的地址是不同的,也就是说创建了新的对象, 而不是把原对象的地址赋给了一个新的引用变量,这就叫做对象拷贝。

    在这里插入图片描述

    注:深拷贝和浅拷贝都是对象拷贝

    二、浅拷贝

    (1)、定义

    被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

    简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

    (2)、浅拷贝实例

    public class ShallowCopy {
        public static void main(String[] args) throws CloneNotSupportedException {
            Teacher teacher = new Teacher();
            teacher.setName("riemann");
            teacher.setAge(28);
    
            Student student1 = new Student();
            student1.setName("edgar");
            student1.setAge(18);
            student1.setTeacher(teacher);
    
            Student student2 = (Student) student1.clone();
            System.out.println("-------------拷贝后-------------");
            System.out.println(student2.getName());
            System.out.println(student2.getAge());
            System.out.println(student2.getTeacher().getName());
            System.out.println(student2.getTeacher().getAge());
    
            System.out.println("-------------修改老师的信息后-------------");
            // 修改老师的信息
            teacher.setName("jack");
            System.out.println("student1的teacher为: " + student1.getTeacher().getName());
            System.out.println("student2的teacher为: " + student2.getTeacher().getName());
    
        }
    }
    
    class Teacher implements Cloneable {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    class Student implements Cloneable {
        private String name;
        private int age;
        private Teacher teacher;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Teacher getTeacher() {
            return teacher;
        }
    
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }
    
        public Object clone() throws CloneNotSupportedException {
            Object object = super.clone();
            return object;
        }
    }
    

    输出结果:

    -------------拷贝后-------------
    edgar
    18
    riemann
    28
    -------------修改老师的信息后-------------
    student1的teacher为: jack
    student2的teacher为: jack
    

    结果分析: 两个引用student1student2指向不同的两个对象,但是两个引用student1student2中的两个teacher引用指向的是同一个对象,所以说明是浅拷贝

    在这里插入图片描述

    三、深拷贝

    (1)、定义

    深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

    简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

    (2)、深拷贝实例

    public class DeepCopy {
        public static void main(String[] args) throws CloneNotSupportedException {
            Teacher teacher = new Teacher();
            teacher.setName("riemann");
            teacher.setAge(28);
    
            Student student1 = new Student();
            student1.setName("edgar");
            student1.setAge(18);
            student1.setTeacher(teacher);
    
            Student student2 = (Student) student1.clone();
            System.out.println("-------------拷贝后-------------");
            System.out.println(student2.getName());
            System.out.println(student2.getAge());
            System.out.println(student2.getTeacher().getName());
            System.out.println(student2.getTeacher().getAge());
    
            System.out.println("-------------修改老师的信息后-------------");
            // 修改老师的信息
            teacher.setName("jack");
            System.out.println("student1的teacher为: " + student1.getTeacher().getName());
            System.out.println("student2的teacher为: " + student2.getTeacher().getName());
        }
    }
    
    class Teacher implements Cloneable {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    class Student implements Cloneable {
        private String name;
        private int age;
        private Teacher teacher;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Teacher getTeacher() {
            return teacher;
        }
    
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }
    
        public Object clone() throws CloneNotSupportedException {
            // 浅复制时:
            // Object object = super.clone();
            // return object;
    
            // 改为深复制:
            Student student = (Student) super.clone();
            // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
            student.setTeacher((Teacher) student.getTeacher().clone());
            return student;
    
        }
    }
    

    输出结果:

    -------------拷贝后-------------
    edgar
    18
    riemann
    28
    -------------修改老师的信息后-------------
    student1的teacher为: jack
    student2的teacher为: riemann
    

    结果分析:
    两个引用student1student2指向不同的两个对象,两个引用student1student2中的两个teacher引用指向的是两个对象,但对teacher对象的修改只能影响student1对象,所以说是深拷贝

    在这里插入图片描述

    展开全文
  • 面试题:深拷贝和浅拷贝(超级详细,有内存图)

    万次阅读 多人点赞 2019-08-07 13:07:34
    拷贝和浅拷贝是经常在面试中会出现的,主要考察你对基本类型和引用类型的理解深度。我在无数次的面试中,应聘者还没有一个人能把这个问题回答情况,包括很多机构的培训老师。这篇文章会让你把基本类型和引用类型...

    这篇文章竟然写了一上午,亲,请怀着感恩的心阅读!!

     

           深拷贝和浅拷贝是经常在面试中会出现的,主要考察你对基本类型和引用类型的理解深度。我在无数次的面试中,应聘者还没有一个人能把这个问题回答情况,包括很多机构的培训老师。这篇文章会让你把基本类型和引用类型的区别搞得清清楚楚,搞清楚这两者的区别,你对任何编程语言的都不怕,因为,这不是js一门语言,是任何编程语言中都需要掌握的知识,而且,在任何编程语言中,两者都是一样的。

     

    深拷贝和浅拷贝主要是针对对象的属性是对象(引用类型)

    一、基本类型和引用类型的区别

    1、先了解内存

       任何编程语言的内存分区几乎都是一样的

     

           内存是存储数据的,不同类型的数据要存储在不同的区域,即分类存放,不同的区域作用和功能也不一样。就像你家里的衣柜一样,也分了不同的区域:如挂西装的区域,放袜子的区域等等,我相信每个人都会把这两个东西放在不同的区域。要不然,当你西装革履地参加一个高档的宴会,手塞在裤兜里,掏出来一只臭袜子,是不是很尴尬!!!哈哈!!!

     

    以下为内存的分区图。内存分为四个区域:栈区(堆栈),堆区,全局静态区,只读区(常量区和代码区)。

     

    https://blog.csdn.net/jiang7701037/article/details/98728249

     

        2、基本类型和引用类型在内存上存储的区别

    现在只看栈区和堆区,不管其它区域,也假定只是局部变量。

     

    以上函数testf在调用时,

           1)、 定义局部变量 age,由于age是局部变量,所以在栈中申请内存空间,起名为age,又由于给age赋的值250是基本类型,所以,值直接存储在栈中。

           2)、定义局部变量arr,由于arr是局部变量,所以在栈中申请空间,但是arr的内存中存储的是什么?由于给arr赋的值不是基本类型,而是引用类型(new出来的),所以,先在堆中申请空间存放数据 12,23,34,。再把堆区的地址赋给arr。

     

    3、到底什么是基本类型和引用类型

          1)、基本类型:就是值类型,即在变量所对应的内存区域存储的是值,如:上面的age变量所对应的内存存储的就是值250.

          2)、引用类型:就是地址类型。

       何为地址:地址就是编号,要地址何用,就是为了容易找到。每个人的家里为什么要有一个唯一的地址,就是在邮寄时,能够找到你家。

    比如:我们最早的超市存包的格子,每个格子都有个编号,你存包时,服务员会把你的东西放在某个格子里,再把这个格子的编号给你(一个牌子)。你购物完毕取包时,直接给服务员你的牌子(有编号),服务员根据你的编号就会找到你的包。这个编号就是格子的地址。内存也是一样的,每个内存都有一个编号,方便cpu查找。要不然,浩瀚的内存海洋,cpu要找到数据靠啥找。

    以上的变量arr就是引用类型,arr所对应的内存中存储着地址,真正的数据是在地址对应的内存区域里,就像,你填写简历时,会在简历的那张纸上写上你家的地址。简历上写你家地址的地方就相当于arr。而你家是根据这个地址可以找到的。简历上写你家地址的地方就相当于引用着你家(可以想象一根无形的线牵引着你家,在简历上的这根无形的线,顺藤摸瓜就能找到你家)。所以叫做引用类型。

       二、基本类型和引用类型在赋值时内存的变化

    你可以认为,赋值就是在拷贝。

    1、基本类型:

    2、引用类型:

     

    如果给arr[0]赋值的话,arr1[0]的值也会发生变化,因为,arr和arr1保存着相同的地址,它门两个引用的数据是共享的。就像你在很多地方(简历的那张纸,户口本上的那张纸)会写上你的家庭地址。这么多张纸都引用着你家。根据一张纸上找到你家,给你家放上一百万的现金(数据改变了,相当于arr[0]=10),再根据另外一张纸的地址也找到了你家,你发现你一百万在(不要给我说被人拿了)

     

    如果在上面的基础上增加一句代码:arr[0]=10;那么内存将会有如下变化:

    ​​

    三、基本类型和引用类型作为函数参数的区别(这个可以不看)

    1、基本类型作为函数的参数

    2、引用类型作为函数的参数:

    四、深拷贝和浅拷贝:

       终于说到了深拷贝和浅拷贝。

    其实在第二点已经说到了拷贝,所谓拷贝,就是赋值。把一个变量赋给另外一个变量,就是把变量的内容进行拷贝。把一个对象的值赋给另外一个对象,就是把一个对象拷贝一份。

    1、基本类没有问题,

    因为,基本类型赋值时,赋的是数据(所以,不存在深拷贝和浅拷贝的问题)。

           如:

        Var x = 100;

        Var y = x; //此时x和y都是100;

       如果要改变y的值,x的值不会改变。

     

    2、引用类型有问题

      因为,引用类型赋值时,赋的值地址(就是引用类型变量在内存中保存的内容),强烈建议把前面的第二点(基本类型和引用类型在赋值时内存的变化)多看几遍,以保证理解深刻。这样,一劳永逸,以后在碰到任何跟引用类型有关的话题(如:继承时,父类的属性是引用类型)都没有问题。

          如:

    var arr1 = new Array(12,23,34)

    Var arr2 = arr1;//这就是一个最简单的浅拷贝

     

    如果要改变arr2所引用的数据:arr2[0]=100时,那么arr1[0]的值也是100。

            原因就是 arr1和arr2引用了同一块内存区域(以上的第二点中有体现)。

            

    这是最简单的浅拷贝,因为,只是把arr1的地址拷贝的一份给了arr2,并没有把arr1的数据拷贝一份。所以,拷贝的深度不够

             

    3、用json对象的方式(也是引用类型)来演示浅拷贝和深拷贝

       

    1)、定义一个json对象(对象的属性也是对象)

    var p = {
    	"id":"007",
    	"name":"刘德华",
    	"books":new Array("三国演义","红楼梦","水浒传")//这是引用类型
    }

     

    内存图:

     

    2)、把该对象p进行复制一份

    • (一)浅拷贝
    var p2 = {};
    for(let key in p){
    	p2[key] = p[key];	
    }
    p2.books[0] ="四国";
    console.log(p2);
    console.log(p);

    在控制台中打印的结果(p和p2的books[0]都变成了“四国”):

    内存:

     

    • (二)深拷贝(初步)
    var p2 = {};
    for(let key in p){
    	if(typeof p[key]=='object'){
    		p2[key]=[];//因为,我上面写的是数组,所以,暂时赋值一个空数组.
    		for(let i in p[key]){
    			p2[key][i] = p[key][i]
    		}
    	}else{
    		p2[key] = p[key];
    	}
    }
    p2.books[0] ="四国";
    console.log(p2);
    console.log(p);

    在控制台中打印的结果(只有p2的books[0]变成了“四国”)

    内存:

     

      (三)深拷贝(最终)

    3.1、深拷贝_如果属性都是json对象,那么用递归的方式

     

    //如果对象的属性是对象(引用类型),属性的属性也是引用类型,即层层嵌套很多.怎么办,只能递归

    //如下对象,要复制:

    var p = {
    	"id":"007",
    	"name":"刘德华",
    	"wife":{
    		"id":"008",
    		"name":"刘德的妻子",
    		"address":{
    			"city":"北京",
    			"area":"海淀区"
    		}
    	}
    }
    
    //写函数
    function copyObj(obj){
    	let newObj={};
    	for(let key in obj){
    		if(typeof obj[key] =='object'){//如:key是wife,引用类型,那就递归
    			newObj[key] = copyObj(obj[key])
    		}else{//基本类型,直接赋值
    			newObj[key] = obj[key];
    		}
    	}
    	return newObj;
    }
    
    let pNew = copyObj(p);
    pNew.wife.name="张三疯";
    pNew.wife.address.city = "香港";
    console.log(pNew);
    console.log(p);

     

    3.2、深拷贝_如果属性是数组等非键值对的对象

          就得单独处理:要么给数组增加一个自我复制的函数(建议这样做),要么单独判断。

    //给数组对象增加一个方法,用来复制自己
    Array.prototype.copyself = function(){
    	let arr = new Array();
    	for(let i in this){
    		arr[i]  = this[i]
    	}
    	return arr;
    }
    
    var p = {
    	"id":"007",
    	"name":"刘德华",
    	"books":new Array("三国演义","红楼梦","水浒传")//这是引用类型
    }
    
    function copyObj(obj){
    	let newObj={};
    	for(let key in obj){
    		if(typeof obj[key] =='object'){//如:key是wife,引用类型,那就递归
    			newObj[key] = obj[key].copyself();
    		}else{//基本类型,直接赋值
    			newObj[key] = obj[key];
    		}
    	}
    	return newObj;
    }
    
    var pNew = copyObj(p);
    pNew.books[0] = "四国";
    console.log(pNew);
    console.log(p);  

    这篇文章竟然写了一上午,亲,请怀着感恩的心阅读

    展开全文
  • Golang深拷贝拷贝

    万次阅读 2019-05-30 23:19:37
    Golang深拷贝拷贝 在了解原型设计模式之前我们需要新知道Golang的深拷贝与浅拷贝之间的区别。 推荐大家新看看Slice 和 Map那么常见的坑:https://blog.csdn.net/weixin_40165163/article/details/90707593 ...
  • 拷贝和浅拷贝的区别

    千次阅读 2020-08-27 11:19:12
    拷贝和浅拷贝 值类型 vs 引用类型 赋值 vs 浅拷贝 vs 深拷贝 对象赋值 浅拷贝拷贝拷贝代码实现 深拷贝代码实现 深度遍历式拷贝 利用反序列化实现深拷贝拷贝和浅拷贝拷贝(shallowCopy)...
  • 秒懂深浅拷贝拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用.【情形一】【情形二】【情形三】深拷贝拷贝多层, 每一级别的数据都会拷贝。深拷贝的实现(递归的方式) 浅拷贝只是拷贝一层, 更深层次对象级别的只...
  • JAVA对象拷贝分为两种方式,一种是引用拷贝,一种是对象拷贝 引用拷贝:和对象拷贝的不同之处在于,引用拷贝只会生成一个新的对象引用地址,但两个地址其最终指向的还是同一个对象; 对象拷贝:这种方式会重新生成...
  • JavaScript专题(五)深浅拷贝

    万次阅读 多人点赞 2020-08-12 18:53:12
    了解拷贝背后的过程,避免不必要的错误 1. 介绍浅拷贝 2. 介绍深拷贝 3. 实现浅拷贝 4. 实现深拷贝 Js专题系列之深浅拷贝,我们一起加油~
  • Kafka零拷贝

    万次阅读 多人点赞 2019-08-15 19:35:10
    实际上是否能使用零拷贝与操作系统相关,如果操作系统提供 sendfile 这样的零拷贝系统调用,则这两个方法会通过这样的系统调用充分利用零拷贝的优势,否则并不能通过这两个方法本身实现零拷贝。 Kafka总结 总...
  • JS中浅拷贝和深拷贝的几种实现方式

    千次阅读 多人点赞 2020-09-22 21:07:29
        深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象的。它们最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用。简单来说,假设B复制了A,当修改B时,看A是否会发生变化,如果A变了,说明...
  • 在C++Primer中(P440)中阐述了一个类中的拷贝控制操作有以下4类: (1)拷贝构造函数 (2)拷贝赋值运算符 (3)析构函数 (4)移动构造函数 (5)移动赋值运算符 其中,(4)和(5)是新的C++标准特性。 ...
  • iOS深拷贝和浅拷贝

    千次阅读 2018-08-01 16:53:35
    拷贝:指针拷贝,不会创建一个新的对象。浅拷贝简单点说就是对内存地址的复制,让目标对象指针和源对象指针指向同一片内存空间 深拷贝: 内容拷贝,会创建一个新的对象。深拷贝就是拷贝地址中的内容,让目标对象...
  •  当出现类的等号赋值时,会调用拷贝函数,在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。 但当数据成员中有指针...
  • 拷贝和浅拷贝的区别和与原理

    千次阅读 2020-05-25 16:52:49
    二、浅拷贝和深拷贝 如图所示: obj2是对obj1的浅拷贝,obj2新建了一个对象,但是obj2对象复制的是obj1的指针,也就是obj1的堆内存地址,而不是复制对象本身。obj1和obj2是共用了内存地址的。 obj3是对obj1的深...
  • 拷贝与浅拷贝 一、数据类型 基本数据类型的特点:直接存储在栈(stack)中的数据 引用数据类型:存储的是该对象在栈中的引用,真实的数据存放在堆内存中 引用数据类型: 引用数据类型在栈中存储了...
  • 拷贝和浅拷贝区别是什么?

    万次阅读 多人点赞 2019-06-18 15:44:47
    拷贝和浅拷贝区别是什么? 复制一个 Java 对象 浅拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。 深拷贝:复制基本类型的属性;...
  • JS深拷贝、浅拷贝 和 使用场景 详解

    千次阅读 2019-10-24 22:51:23
    拷贝: 当对某个数据(数组或对象)进行拷贝后,修改新数据(拷贝后的数据)里面第1层的数据是不会影响老数据(被拷贝的数据)的,但是如果还要第2层 或 更深层次的数据(复杂数据类型),它仍然是有关联的,如果...
  • 拷贝技术的原理与在java中应用

    万次阅读 2020-11-19 11:15:08
    拷贝技术的原理与应用 零拷贝(Zero-copy)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。 零拷贝技术可以减少数据...
  • java中的深拷贝与浅拷贝

    千次阅读 2019-01-03 19:56:28
    目录概念浅拷贝快速入门例子(不带对象属性)深拷贝快速入门例子(不带对象属性)属性未实现Cloneable 例子(浅拷贝)属性实现Cloneable 例子(浅拷贝) 概念 浅拷贝(浅复制、浅克隆): 被复制对象的所有变量都含有与...
  • python:深拷贝,浅拷贝,赋值引用

    万次阅读 多人点赞 2019-05-23 21:08:15
    1. python的复制,深拷贝和浅拷贝的区别 在python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, a...
  • c++拷贝构造函数

    千次阅读 多人点赞 2019-06-28 16:22:40
    什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。 下面看一个类对象...
  • 原来 8 张图,就可以搞懂「零拷贝」了

    万次阅读 多人点赞 2020-09-23 17:07:44
    磁盘可以说是计算机系统最慢的硬件之一,读写速度相差内存 10 倍以上,所以针对优化磁盘的技术非常的多,比如零拷贝、直接 I/O、异步 I/O 等等,这些优化的目的就是为了提高系统的吞吐量,另外操作系统内核中的磁盘...
  • Js复制对象/克隆对象 Js浅拷贝与深拷贝拷贝和深拷贝的实现方法 前言 学习Js克隆一个对象,作为准备工作,需要理解Js中的数据类型和按值传递:Js中的数据类型和按值传递 浅拷贝最后两种方法不理解的话,可以读es5...
  • JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象;序列化的作用是存储(对象本身存储的只是一个...
  • 拷贝原理详解

    万次阅读 多人点赞 2019-11-11 20:20:15
    传统的 Linux 操作系统的标准 I/O 接口是基于数据拷贝操作的,即 I/O 操作会导致数据在操作系统内核地址空间的缓冲区和应用程序地址空间定义的缓冲区之间进行传输。这样做最大的好处是可以减少磁盘 I/O 的操作,因为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,704,527
精华内容 681,810
关键字:

拷贝