C++ 深拷贝浅拷贝

一、概念

深拷贝:指的是拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝。这样进行深拷贝后的拷贝对象就和源对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。

浅拷贝:指的是拷贝一个对象时,仅仅拷贝对象的引用进行拷贝,但是拷贝对象和源对象还是引用同一份实体。此时,其中一个对象的改变都会影响到另一个对象。

浅拷贝示例:

#include
using namespace std;

/*
深拷贝浅拷贝
1、定义一个Array类,数据成员m_iCount,成员函数:构造、析构、拷贝构造、成员封装,通过此例体会浅拷贝
2、增加数据成员m_pArr,并增加m_pArr地址查看函数,同时改造构造函数、拷贝构造和析构,体会深拷贝原理和必要性
*/

class Array
{
public:
	Array();
	Array(const Array &arr);
	~Array();
	void setCount(int count);
	int getCount();
private:
	int m_iCount;
};

Array::Array()
{
	cout<<"Array()"<

运行结果:

C++ 深拷贝浅拷贝_第1张图片

用arr1实例化arr2的时候,就将arr1中的m_iCount赋值给了arr2中的m_iCount,这个代码中的拷贝构造函数中实现的是浅拷贝。那么浅拷贝会存在哪些问题呢?我们来看下一个代码

#include
using namespace std;

/*
深拷贝浅拷贝
1、定义一个Array类,数据成员m_iCount,成员函数:构造、析构、拷贝构造、成员封装,通过此例体会浅拷贝
2、增加数据成员m_pArr,并增加m_pArr地址查看函数,同时改造构造函数、拷贝构造和析构,体会深拷贝原理和必要性
*/

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;
};

Array::Array(int count)
{
    m_iCount = count;
    m_pArr = new int[m_iCount];
    cout<<"Array()"<

运行结果:

C++ 深拷贝浅拷贝_第2张图片

根据运行结果,我们发现通过arr1实例化出来的arr2的m_pArr的值与arr1相同,说明这两个指针指向了同一块内存,在调用析构函数的时候,arr1会释放一遍,arr2也会释放一遍,但是他们指向同一块内存,所以相当于让同一块内存释放两遍,会造成程序崩溃!!!

那么如何解决这样的问题呢?

利用深拷贝
 

#include
using namespace std;

/*
深拷贝浅拷贝
1、定义一个Array类,数据成员m_iCount,成员函数:构造、析构、拷贝构造、成员封装,通过此例体会浅拷贝
2、增加数据成员m_pArr,并增加m_pArr地址查看函数,同时改造构造函数、拷贝构造和析构,体会深拷贝原理和必要性
*/

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::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()"<

运行结果:

C++ 深拷贝浅拷贝_第3张图片

我们可以看arr1中和arr2中的两个指针指向了不同的内存,arr2成功地拷贝了arr1中的数据,并且执行了两次析构函数

总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

注意:

  • 对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数,是浅拷贝。
  • 在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。

学习参考:

C++面试题之浅拷贝和深拷贝的区别

一个完整的自定义类实现可参考:C++笔试题之String类的实现

 

 

 

 

 

 

你可能感兴趣的:(C++,深拷贝,浅拷贝)