深拷贝&浅拷贝

浅拷贝,实际上就是对指针进行拷贝,两个指针指向同一块地址空间。而深拷贝不仅仅是对指针进行拷贝,而且对指针指向的内容进行拷贝。经深拷贝两个指针指向不同的地址空间。

class String
{
public:
	String(const char* _pStr = "")//构造函数
		:m_iSize(strlen(_pStr)+1)
	{
		m_pStr = new char[m_iSize];
		strcpy(m_pStr, _pStr);
		m_pStr[m_iSize] = '\0';
	}

	String(const String& _string)//拷贝构造函数
		:m_iSize(_string.m_iSize)
	{
		if (this != &_string)
		{
			m_pStr = _string.m_pStr;
		}
	}
	~String()//析构函数
	{
		if (NULL != m_pStr)
		{
			delete[] m_pStr;
			m_pStr = NULL;
		}
	}
private:
	char* m_pStr;
	int m_iSize;
};

测试函数

 

void FunTest()
{
	String str1("hello");
	String str2(str1);
}

这个程序会出现问题,导致程序奔溃

 

代码分析:

1.String str1("hello");

调用的是String类的构造函数。首先,给m_pStr分配空间,然后,将形参的内容拷贝到m_pStr中。

2.String str2(str1);

调用的是String类的拷贝构造函数。首先,根据形参m_iSize初始化m_iSize,然后,让m_pStr指向形参m_pStr空间。

3.函数执行过程中,局部变量str2被析构,调用析构函数,将str2.m_pStr所在的空间释放掉。

4.str1被析构,调用析构函数,str1.m_pStr一直指向申请空间,去释放已经str2.m_pStr释放的空间,相同的空间被释放了两次,因此程序奔溃。

 

浅拷贝:也称位拷贝,编译器只是直接将指针的值拷贝过来,结果多个对象共用同一块空间,当一个对象将这块空间释放之后,另一些对象不知道这块空间已经还给了系统,以为有效,所以在对这块空间进行操作时,发生了访问违规。那么,深拷贝就能解决浅拷贝不能解决的问题,构造对象时拷贝一块跟当前对象一样的大数据块,析构时各自释放各自的数据块。

深拷贝采取了在堆内存中申请新的空间来存储数据,在拷贝构造函数中申请了新的内存空间,使得两个对象的成员变量不指向同一个内存空间,除非需要这样做。

class String
{
public:
	String(const char *pStr = "")//构造函数
	{
		if (NULL == pStr)
		{
			_pStr = new char[1];
			*_pStr = '\0';
		}
		else
		{
			_pStr = new char[strlen(pStr) + 1];
			strcpy(_pStr, pStr);
		}
	}

	~String()//析构函数
	{
		if (NULL != _pStr)
		{
			delete[] _pStr;
			_pStr = NULL;
		}
	}

	/*
	//深拷贝
	  //普通版
	String(const String &s) //拷贝构造
		:_pStr(new char[strlen(s._pStr) + 1])
	{
		strcpy(_pStr, s._pStr);
	}
	String& operator=(const String& s)//赋值运算符重载
	{
		if (this != &s)
		{
			char* tmp = new char[strlen(s._pStr) + 1];//开辟新空间
			strcpy(tmp, s._pStr);//拷贝
			delete[] _pStr;//释放旧空间
			strcpy(_pStr, tmp);
		}
		return *this;
	}
	*/

	 //简洁版
	String(const String &s)//拷贝构造
		:_pStr(NULL)//解决_pStr为野指针的情况
	{
		String tmp(_pStr);
		swap(_pStr, tmp._pStr);//交换
	}

	String& operator=(const String& s)//赋值运算符重载
	{
		if (this != &s)
		{
			String tmp(_pStr);
			swap(_pStr, tmp._pStr);//交换
		}
		return *this;
	}


private:
	char* _pStr;
};

void FunTest()
{
	String str1("hello");
	String str2(str1);
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值