深拷贝与浅拷贝

-------------------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 = newint[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");

return0;

}

  

  

运行一览:

  

深拷贝与浅拷贝

  

  

  

  

  

程序 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 = newint[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 = newint[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");

return0;

}

  

  

运行一览:

  

深拷贝与浅拷贝

  

  

  

  

  

  

  

  

  

  

【made by siwuxie095】