String类深拷贝的模拟实现

深拷贝浅拷贝分析:

浅拷贝:也称位拷贝,编译器只是直接将指针的值拷贝过来,结果多个对象共用同一块内存,当一个对象将这块内存释放掉之后,另一些对象不知道该块空间已经还给了系统,以为还有效,所以在对这段内存进行释放操作的时候,一个内存空间被释放多次,发生了访问违规,程序崩溃。

如图:


深拷贝:为了解决浅拷贝的问题,深拷贝则不是直接将指针的值拷贝,它是为指针p2开辟与p1相同大小的内存空间,然后将p1所指的内存str[]内容拷贝到p2自己空间中,这时由于p1、p2指向的是各自不同的内存空间,delete时只释放自己的内存,不会出现访问违规。

如图:


string类的实现则不能使用浅拷贝的方法,在这里则以深拷贝的方法模拟实现它的传统写法与现代写法简洁版:

代码如下:

#pragma once
#include <string.h>
//String类的实现
class String
{
public:
	//构造函数
	String(const char* pStr=NULL)
	{
		if(pStr==NULL)
		{
			_pStr=new char[1];
			*_pStr='\0';
		}
		else
		{
			_pStr=new char[strlen(pStr)+1];
			strcpy(_pStr,pStr);//strcpy拷贝了'\0'
		}
	}

	//析构函数
	String()
	{
		if(_pStr!=NULL)
		{
			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* pTemp=new char[strlen(s._pStr)+1];
			strcpy(pTemp,s._pStr);
			delete[] _pStr;
			_pStr=pTemp;
		}
		return *this;
	}

	//简洁版

	//拷贝构造函数
	/*String(const String& s)
		:_pStr(NULL)
	{
		String temp(s._pStr);//调用构造函数
		std::swap(_pStr,temp._pStr);//交换内容
	}

	//赋值运算符重载
	String& operator=(const String& s)
	{
		if(this!=&s)
		{
			String temp(s);//String temp(s._pStr)//创建临时对象
			std::swap(_pStr,temp._pStr);  //交换内容
		}//出了作用域临时对象析构,即析构了_pStr原内容
		return *this;
	}

	String& operator=(String s)  //值传递:调用了一次拷贝构造函数,并不会改变s原对象内容
	{
		std::swap(_pStr,s._pStr);  //交换内容,出了函数由于为值传递s._pStr析构,即析构了_pStr原内容
		return *this;
	}*/

private:
	char* _pStr;
};
void Test()
{
	String s1("hello");
	String s2("world");
	String s3(s1);
	s3=s2;
}
在以上实现中,1.特别注意的为赋值运算符重载的实现,当两个string对象s2、s3相互赋值时,如以上代码s3=s2,因为s3之前也有自己的内存空间,所以在赋值前,一定要释放s3原本的内存,否则会造成内存泄漏;

2.在简洁版实现中思想为:以一个临时对象内容交换现在对象内容,即实现了现有对象内容重新赋值,也使它原本内容存于临时对象中,出了函数作用域自动析构销毁。

你可能感兴趣的:(String类深拷贝的模拟实现)