zoukankan      html  css  js  c++  java
  • 深拷贝与浅拷贝

    -------------------siwuxie095

       

       

       

       

       

       

       

       

       

    深拷贝 浅拷贝

       

       

    对象间的拷贝没那么简单,大致分为两种情况:一种叫做 深拷贝,一种叫做 浅拷贝

       

       

    看如下实例:定义一个数组类:Array

       

       

       

       

    使用时:

       

    arr1 在实例化时,会调用构造函数,而使用 arr1 初始化 arr2,

    arr2 在实例化时,就会调用拷贝构造函数,参数其实就是 arr1

       

       

       

       

    上面的例子比较简单,对其再做稍微地修改:加一个 int 型指针,该指针

    在构造函数中从堆中申请了一段内存,且指向了堆中的这段内存,内存的

    大小就是 m_iCount,而拷贝构造函数的实现方法还是进行简单的拷贝

       

       

       

    使用时:arr1 执行默认构造函数,而 arr1 初始化 arr2 时,就会调用拷贝

    构造函数,但这两个例子都只是将数据成员的值进行了简单的拷贝,这种

    拷贝模式称为 浅拷贝

       

       

       

    但对于第一个例子,使用浅拷贝的方式实现拷贝构造函数并没有任何问题,

    而对于第二个例子,肯定是有问题的

       

    经过浅拷贝之后,对象 arr1 中的指针和对象 arr2 中的指针势必会指向同

    一块内存,因为在拷贝构造函数中,将 arr1 的 m_pArr 赋值给了 arr2 的

    m_pArr,使得这两个变量中存放的是同一个值

       

       

       

    此时,如果先给 arr1 的 m_pArr 赋了一些值,再去给 arr2 的 m_pArr

    赋值时,这段内存就会被重写,覆盖掉 arr1 的 m_pArr 的值,最严重

    的是,当销毁 arr1 对象时,为了避免内存泄露,肯定会释放掉 arr1 中

    m_pArr 所指向的这段内存,如果已经释放掉这段内存,再去销毁 arr2

    对象时,也会以同样的方式释放掉 arr2 中 m_pArr 所指向的这段内存

       

       

    相当于同一块内存被释放了两次,这种情况肯定是有问题的,面对这种

    问题,计算机会以崩溃的方式向你抗议,提示的错误信息因为晦涩难懂,

    不能直奔主题,同样使得初学者感到崩溃

       

       

       

       

       

    所以,希望拷贝构造函数所完成的工作应该是这样的:两个对象的指针

    所指向的应该是不同的内存,拷贝时不是将指针的地址简单地拷贝过来,

    而是将指针所指向的内存中的每一个元素依次拷贝过来

       

       

       

       

    代码应该写成这样:

       

       

       

    两种拷贝方式有着本质的区别,当进行对象拷贝时,不是简单地做值的

    拷贝,而是将堆中内存的数据也进行拷贝,这种拷贝模式称为 深拷贝

       

       

       

       

    程序 1:浅拷贝

       

    Array.h:

       

    class Array

    {

    public:

    Array();

    Array(int count);

    Array(const Array &arr);

    ~Array();

    void setCount(int count);

    int getCount();

    void printAddr();//地址查看函数

    void printArr();

    private:

    int m_iCount;//数组元素个数

    int *m_pArr;

    };

       

       

       

    Array.cpp:

       

    #include"Array.h"

    #include <iostream>

    using namespace std;

       

       

    Array::Array()

    {

    cout << "Array" << endl;

    }

       

    Array::Array(int count)

    {

    m_iCount = count;

    m_pArr = new int[m_iCount];

    cout << "Array" << endl;

    }

       

    Array::Array(const Array &arr)

    {

    m_pArr = arr.m_pArr;

    m_iCount = arr.m_iCount;

    cout << "Array &" << endl;

    }

       

    Array::~Array()

    {

    delete[]m_pArr;

    m_pArr = NULL;

    cout << "~Array" << endl;

    }

       

    void Array::setCount(int count)

    {

    m_iCount = count;

    }

       

    int Array::getCount()

    {

    return m_iCount;

    }

       

    void Array::printAddr()

    {

    cout << "m_pArr的值是:" << m_pArr << endl;

    }

       

    void Array::printArr()

    {

    for (int i = 0; i < m_iCount;i++)

    {

    cout << m_pArr[i] << " ";

    }

    }

       

       

       

    main.cpp:

       

    #include <stdlib.h>

    #include "Array.h"

    #include <iostream>

    using namespace std;

       

       

    //浅拷贝:将值直接拷贝过去

    int main(void)

    {

    Array arr1;

    arr1.setCount(5);

    Array arr2(arr1);

    cout << "arr2.m_iCount:" << arr2.getCount() << endl;

    system("pause");

    return 0;

    }

       

       

    运行一览:

       

       

       

       

       

       

    程序 2:深拷贝

       

    Array.h:

       

    class Array

    {

    public:

    Array(int count);

    Array(const Array &arr);

    ~Array();

    void setCount(int count);

    int getCount();

    void printAddr();//地址查看函数

    void printArr();

    private:

    int m_iCount;//数组元素个数

    int *m_pArr;

    };

       

       

       

    Array.cpp:

       

    #include"Array.h"

    #include <iostream>

    using namespace std;

       

       

    Array::Array(int count)

    {

    m_iCount = count;

    m_pArr = new int[m_iCount];

    for (int i = 0; i < m_iCount;i++)

    {

    m_pArr[i] = i;

    }

    cout << "Array" << endl;

    }

       

    Array::Array(const Array &arr)

    {

    m_iCount = arr.m_iCount;

    m_pArr = new int[m_iCount];//给当前的arr2申请一块新的内存

    for (int i = 0; i < m_iCount;i++)

    {

    m_pArr[i] = arr.m_pArr[i];//只是将arr1的值拷贝给arr2

    }

    cout << "Array &" << endl;

    }

       

    //此为浅拷贝:

    //arr2的指针和arr1的指针指向同一块内存,当给arr1赋值后再给arr2赋值,会覆盖掉arr1的值

    //在析构时同一块内存会delete两次 导致错误

    //Array::Array(const Array &arr)

    //{

    // m_pArr = arr.m_pArr;

    // m_iCount = arr.m_iCount;

    // cout << "Array &" << endl;

    //}

       

    Array::~Array()

    {

    //析构时的内存不同,正常释放

    delete[]m_pArr;

    m_pArr = NULL;

    cout << "~Array" << endl;

    }

       

    void Array::setCount(int count)

    {

    m_iCount = count;

    }

       

    int Array::getCount()

    {

    return m_iCount;

    }

       

    void Array::printAddr()

    {

    cout << "m_pArr的值是:" << m_pArr << endl;

    }

       

    void Array::printArr()

    {

    for (int i = 0; i < m_iCount; i++)

    {

    cout << m_pArr[i] << " ";

    }

    cout << endl;

    }

       

       

       

    main.cpp:

       

    #include <stdlib.h>

    #include "Array.h"

    #include <iostream>

    using namespace std;

       

    //深拷贝:先申请一段内存,再将传入进来的对象的对应

    //位置的内存拷贝到申请的内存中去

    int main(void)

    {

    Array arr1(5);

    Array arr2(arr1);

    arr1.printAddr();

    arr2.printAddr();

    arr1.printArr();

    arr2.printArr();

       

       

    system("pause");

    return 0;

    }

       

       

    运行一览:

       

       

       

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    Flask 随记
    Notes on Sublime and Cmder
    Algorithms: Design and Analysis Note
    LeetCode 215 : Kth Largest Element in an Array
    LeetCode 229 : Majority Element II
    LeetCode 169 : Majority Element
    LeetCode 2:Add Two Numbers
    LeetCode 1:Two Sum
    Process and Kernel
    安装好scala后出现“找不到或无法加载主类”的问题
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6795505.html
Copyright © 2011-2022 走看看