深拷贝与浅拷贝

-------------------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】

原文地址:https://www.cnblogs.com/siwuxie095/p/6795505.html