浅拷贝
//Array.h
class Array
{
public:
Array();//定义一个构造函数
Array(const Array &arr);//定义一个拷贝构造函数
~Array();
void setCount(int count);
int getCount();
private:
int m_iCount;
};
//Array.cpp
#include "Array.h"
#include <iostream>
using namespace std;
Array::Array()
{
cout << "Array()" << endl;
}
Array::Array(const Array &arr)
{
m_iCount = arr.m_iCount;
cout << "Array(const Array &arr)" << endl;
}
Array::~Array()
{
cout << "~Array()" << endl;
}
void Array::setCount(int count)
{
m_iCount = count;
}
int Array::getCount()
{
return m_iCount;
}
//demo.cpp
#include <iostream>
#include <stdlib.h>
#include "Array.cpp"
int main()
{
Array arr1;
arr1.setCount(5);
Array arr2(arr1);
cout << "arr2.m_iCount" << " " << arr2.getCount()<< endl;
return 0;
}
从运行结果看,第一行打印出的是构造函数,也就是说arr1实例化的时候调用的是构造函数;第二行打印出的是拷贝构造函数,也就是说arr2实例化的时候调用的是拷贝构造函数;第三行打印出的是arr2中m_iCount的值为5,这就说明我们用arr1去实例化arr2的时候,也将arr1中的m_iCount的值给了arr2中的m_iCount。这就是浅拷贝,其原理就是将值直接拷贝过去。但是浅拷贝有的时候会带来一些问题,下面我们来看都带来哪些问题,以及如何解决这些问题。
浅拷贝的问题
//array.h
class Array
{
public:
Array(int count);//定义一个构造函数
Array(const Array &arr);//定义一个拷贝构造函数
~Array();
void setCount(int count);
int getCount();
void printAddr();//新增 查看地址函数
private:
int m_iCount;
int *m_pArr; //新增数据成员: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];
cout << "Array()" << endl;
}
Array::Array(const Array &arr)
{
m_iCount = arr.m_iCount;
//拷贝的是内存地址
m_pArr = arr.m_pArr;这里先用浅拷贝实现方式来看看会有什么后果?
cout << "Array(const Array &arr)" << 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 value is :"<< m_pArr <<endl;
}
//demo.cpp
#include <iostream>
#include <stdlib.h>
#include "Array.cpp"
using namespace std;
int main()
{
Array arr1(5);
arr1.setCount(5);
Array arr2(arr1);//通过Arr1来实例化arr2
cout << "in arr1"<<endl;
arr1.printAddr();
cout << "in arr2"<<endl;
arr2.printAddr();
//cout << "arr2.m_iCount" << " " << arr2.getCount()<< endl;
return 0;
}
从运行结果来看,我们发现arr1中的m_pArr的值与arr2中的m_pArr的值是一样的,也就是说arr1中的m_pArr与arr2中的m_pArr都指向了同一块内存。此前在析构函数中,我们做了删除工作(delete []m_pArr),这就意味着arr1会删除一次,arr2也会删除一次(因为它们指向的是同一块内存,所以相当于让同一块内存释放了两次),这就一定会造成运行时错误。
深拷贝
我们可以看到,此前我们使用的是浅拷贝,直接赋值的方式来进行拷贝的(m_iCount = arr.m_iCount;m_pArr = arr.m_pArr;//浅拷贝实现方式)。深拷贝的方式则需要在拷贝构造函数中给当前的这个指针先分配一段内存,然后将传入的对象的对应位置的值拷贝到新申请的这段内存中区。那么我们来修改一下构造函数和拷贝构造函数如下:
//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; //新增数据成员: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 = arr.m_pArr;这里先用浅拷贝实现方式来看看会有什么后果?
//===========================
//深拷贝
m_pArr = new int[m_iCount];
for(int i=0;i< m_iCount;i++)
{
m_pArr[i] = arr.m_pArr[i];
}
cout << "Array(const Array &arr)" << 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 value is :"<< m_pArr <<endl;
}
void Array::printArr()
{
for(int i = 0;i < m_iCount; i++)
{
cout << m_pArr[i]<<endl;
}
}
//demo.cpp
#include <iostream>
#include <stdlib.h>
#include "Array.cpp"
using namespace std;
int main()
{
Array arr1(5);
arr1.setCount(5);
Array arr2(arr1);//通过Arr1来实例化arr2
cout << "in arr1"<<endl;
arr1.printAddr();
cout << "in arr2"<<endl;
arr2.printAddr();
cout <<"value of arr1 in m_pArr is "<<endl;
arr1.printArr();
cout <<"value of arr2 in m_pArr is "<<endl;
arr2.printArr();
//cout << "arr2.m_iCount" << " " << arr2.getCount()<< endl;
return 0;
}
从结果我们可以看到,这个时候arr1和arr2中m_pArr的地址已经不相同了,可见它们指向了不同的内存