zoukankan      html  css  js  c++  java
  • 1.浅拷贝和深拷贝

    一.浅拷贝

    对于基本类型的数据以及简单的对象,它们之间的拷贝非常简单,就是按位复制内存。例如:

    class Base{
    public:
        Base(): m_a(0), m_b(0){ }
        Base(int a, int b): m_a(a), m_b(b){ }
    private:
        int m_a;
        int m_b;
    };
    
    int main(){
        int a = 10;
        int b = a;  //拷贝
    
        Base obj1(10, 20);
        Base obj2 = obj1;  //拷贝
    
        return 0;
    }

    b 和 obj2 都是以拷贝的方式初始化的,具体来说,就是将 a 和 obj1 所在内存中的数据按照二进制位(Bit)复制到 b 和 obj2 所在的内存,这种默认的拷贝行为就是浅拷贝,这和调用 memcpy() 函数的效果非常类似。

    对于简单的类,默认的拷贝构造函数一般就够用了,我们也没有必要再显式地定义一个功能类似的拷贝构造函数。但是当类持有其它资源时,例如动态分配的内存指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显式地定义拷贝构造函数,以完整地拷贝对象的所有数据。

    二.深拷贝

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    //变长数组类
    class Array{
    public:
        Array(int len);
        Array(const Array &arr);  //拷贝构造函数
        ~Array();
    public:
        int operator[](int i) const { return m_p[i]; }  //获取元素(读取)
        int &operator[](int i){ return m_p[i]; }  //获取元素(写入)
        int length() const { return m_len; }
    private:
        int m_len;
        int *m_p;
    };
    
    Array::Array(int len): m_len(len){
        m_p = (int*)calloc( len, sizeof(int) );
    }
    
    Array::Array(const Array &arr){  //拷贝构造函数
        this->m_len = arr.m_len;
        this->m_p = (int*)calloc( this->m_len, sizeof(int) );
        memcpy( this->m_p, arr.m_p, m_len * sizeof(int) );
    }
    
    Array::~Array(){ free(m_p); }
    
    //打印数组元素
    void printArray(const Array &arr){
        int len = arr.length();
        for(int i=0; i<len; i++){
            if(i == len-1){
                cout<<arr[i]<<endl;
            }else{
                cout<<arr[i]<<", ";
            }
        }
    }
    
    int main(){
        Array arr1(10);
        for(int i=0; i<10; i++){
            arr1[i] = i;
        }
       
        Array arr2 = arr1; // 此处会调用拷贝构造函数
        arr2[5] = 100;
        arr2[3] = 29;
       
        printArray(arr1);
        printArray(arr2);
       
        return 0;
    }

    运行结果:

    本例中我们显式地定义了拷贝构造函数,它除了会将原有对象的所有成员变量拷贝给新对象,还会为新对象再分配一块内存,并将原有对象所持有的内存也拷贝过来。这样做的结果是,原有对象和新对象所持有的动态内存是相互独立的,更改一个对象的数据不会影响另外一个对象,本例中我们更改了 arr2 的数据,就没有影响 arr1。

    这种将对象所持有的其它资源一并拷贝的行为叫做深拷贝,我们必须显式地定义拷贝构造函数才能达到深拷贝的目的。

  • 相关阅读:
    Java实现KMP算法
    字符串匹配的KMP算法
    Apache与Tomcat 区别和联系
    二叉树中两个节点的最近公共父节点
    Git使用详细教程
    动画讲解 Eclipse 常用快捷键
    Android系统SD卡各类文件夹名称
    Chrome 控制台不完全指南
    JavaScript入门学习书籍的阶段选择
    从入门到放弃的第二周(面向对象)......day.6.。。。。。对象,类,方法;
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/7120194.html
Copyright © 2011-2022 走看看