String类与深浅拷贝

浅拷贝

1、概念:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之, 浅拷贝仅仅复制所考虑的对象,而不是复制它所引用的对象。
2、举例

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

String(const String& s)
{
	strcpy(_pStr,s._pStr);
}

String& operator = (const String& s)
{
	if (_pStr != s._pStr)
	{
		_pStr = s._pStr;
	}
	return *this;
}

	~String()
	{
		if (NULL != _pStr)
		{
			delete[] _pStr;
			_pStr = NULL;
		}
	}
private:
	char* _pStr;
};
void FunTest()
{
	String s0;
	String s1 = ("hello");
	String s2(s1);
String s3 = s1;
}
int main()
{
	FunTest();
	return 0;
}

浅拷贝优化一不能实现所有的拷贝///

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

	String(String& s)//拷贝构造函数
		:_pStr(s._pStr)//当前指针和s指针指向同一个空间
		,_pCount(++s._pCount)
	{}

	String& operator = (String& s)//赋值运算符重载
	{
		if (_pStr != s._pStr)//判断是否自我赋值
		{
			if (0 == --_pCount)//判断当前指向this指针所指空对象的个数是否为0,如果为0就释放该空间
			{
				delete[]_pStr;
			}
				_pCount = ++s._pCount;//如果不为0指向新空间,则指向该空间对象数加1
				_pStr = s._pStr;
		}
		return *this;
	}

	~String()//析构函数
	{
		if (0 == _pCount)
		{
			delete[] _pStr;
			_pStr = NULL;
		}
	}
private:
	char* _pStr;
	int _pCount;
};
void FunTest()
{
	String s1 = ("hello");
	String s2(s1);//拷贝构造
	String s3;
	s3 = s1;//赋值重载
}
int main()
{
	FunTest();
	return 0;
}

浅拷贝优化二可以实现部分拷贝

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

	String(String& s)//拷贝构造函数
		:_pStr(s._pStr)//当前指针和s指针指向同一个空间
	{
		++_pCount;
	}

	String& operator = (String& s)//赋值运算符重载
	{
		if (_pStr != s._pStr)//判断是否自我赋值
		{
			if (0 == --_pCount)//判断当前指向this指针所指空对象的个数是否为0,如果为0就释放该空间
			{
				delete[]_pStr;
			}
			++_pCount;//如果不为0指向新空间,则指向该空间对象数加1
			_pStr = s._pStr;
		}
		return *this;
	}

	~String()//析构函数
	{
		if (0 == _pCount)
		{
			delete[] _pStr;
			_pStr = NULL;
		}
	}
private:
	char* _pStr;
	static int _pCount;//类里声明
};

int String::_pCount = 0;//类外定义


void FunTest()
{
	String s1 = ("hello");
	String s2(s1);//拷贝构造


	String s3(s1);
	s3 = s1;//赋值重载


//static不能处理下面这种//
	//String s1 = ("hello");
	//String s2(s1);
	//String s4("world");
	//String s5(s4);
	//s5 = s2;
}
int main()
{
	FunTest();
	return 0;
}


/浅拷贝3所有类型可以全部实现

class String
{
public:
	String(char* pStr = "")//构造函数浅拷贝
		:_pCount(new int(1))//开辟计数空间赋值为1
	{
		if (NULL == pStr)
		{
			_pStr = new char[1];
			*_pStr = '\0';
		}
		else
		{
			_pStr = new char[strlen(pStr)+1];
			strcpy(_pStr,pStr);
		}
	}

	String(String& s)//拷贝构造函数
		:_pStr(s._pStr)//当前指针和s指针指向同一个空间
		,_pCount(s._pCount)//两个对象指向同一个计数空间
	{
		++(*_pCount);//多了一个对象加1
	}

	String& operator = (String& s)//赋值运算符重载
	{
		if (_pStr != s._pStr)//判断是否自我赋值
		{
			if (0 == --(*_pCount))//当前对象引用计数加1,如果为0就释放该空间
			{
				delete[]_pStr;
				delete _pCount;

			}
			_pStr = s._pStr;
			_pCount = s._pCount;//指向新的对象引用计数
			++(*_pCount);//如果不为0新空间引用计数加1
		}
		return *this;
	}

	~String()//析构函数
	{
		if (0 == (*_pCount))
		{
			delete[] _pStr;
			delete _pCount;
			_pStr = NULL;
			_pCount = NULL;
		}
	}
private:
	char* _pStr;
	int* _pCount;
};

void FunTest()
{
	String s1 = ("hello");
	String s2(s1);//拷贝构造


	String s3(s1);
	s3 = s1;//赋值重载

	String s4("world");
	String s5(s4);
	s5 = s2;
}
int main()
{
	FunTest();
	return 0;
}

深拷贝

1、概念:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量,那些引用其他对象的变量将指向被复制的对象,而不是原来有那些引用的对象,换言之, 深复制把要复制的对象所引用的对象都复制一遍
2、举例
/深拷贝普通版///
class String
{
public:
	String(char* pStr = "")//构造函数的构造函数
	{
		if (NULL == pStr)//判断是否为空,若为空,开辟一个大小为1的空间
		{
			_pStr = new char[1];
			*_pStr = '\0';
		}
		else
		{
			_pStr = new char[strlen(pStr)+1];
			strcpy(_pStr,pStr);
		}
	}
	String(const String& s)//深拷贝拷贝构造函数
		:_pStr(new char[strlen(s._pStr)+1])//初始化列表给_pStr开辟新空间,防止后面析构函数释放该空间出错。
	{
		strcpy(_pStr,s._pStr);
	}

	String& operator = (const String &s)//深拷贝赋值运算符重载
	{
		if (this != &s)//判断是否自己给自己赋值
		{
///

			//delete[]_pStr;//释放当前this指针所指的空间
			//_pStr = new char [strlen(s._pStr)+1];
			//strcpy(_pStr,s._pStr);

///上面的方法存在问题,如果新开辟空间失败,原this指针所指的就发生改变///

			char *pTmp = new char[strlen(s._pStr)+1];//创建临时指针变量,指向新开辟的地址
			strcpy(pTmp,s._pStr);//s里的值拷贝到临时指针变量所指的空间
			delete[]_pStr;//释放当前this指针所指的空间
			_pStr = pTmp;//当前this指针指向临时变量所指的空间
		}
		return *this;
	}

	~String()//深拷贝析构函数
	{
		if (NULL != _pStr)
		{
			delete[] _pStr;
			_pStr = NULL;
		}
	}
private:
	char * _pStr;
};
void FunTest()
{
	String s1 = ("hello");
	String s2(s1);
	String s3 = s1;	 
}
int main()
{
	FunTest();
	return 0;
}

///深拷贝简洁版/
class String
{
public:
	String(const char* pStr = "")//深拷贝构造函数
	{
		if (NULL == pStr)//判断是否为空,若为空,开辟一个大小为1的空间
		{
			_pStr = new char[1];
			*_pStr = '\0';
		}
		else
		{
			_pStr = new char[strlen(pStr) + 1];
			strcpy(_pStr, pStr);//交换指针
		}
	}
	String(const String& s)//深拷贝拷贝构造函数
		:_pStr(NULL)//初始化列表给_pStr指向空,防止后面析构函数释放该空间出错。
	{
		String str(s._pStr);//创建临时对象和当前string内容相同
		std::swap(_pStr, str._pStr);//当前this指针和临时对象的指针交换
	}

	String& operator = (const String& s)//赋值运算符重载<1>
	{
		if (this != &s)//判断是否自我交换
		{
			String str(s);//调拷贝构造函数
			std::swap(_pStr, str._pStr);//交换指针所指的空间
		}
		return *this;
	}

	String& operator = (String s)//赋值运算符重载<2>,值的形式传递,创建临时变量
	{
		std::swap(_pStr, s._pStr);
		return *this;
	}

	~String()//深拷贝的析构函数
	{
		if (NULL != _pStr)
		{
			delete[] _pStr;
			_pStr = NULL;
		}
	}
private:
	char* _pStr;
};

void FunTest()
{
	string s1("hello");
	string s2(s1);
	string s3;
	s3 = s2;
}
int main()
{
	FunTest();
	system("pause");
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值