【C++】模拟实现string类(版本二:用写时拷贝来实现)

1.什么是写时拷贝

     介绍写时拷贝之前,我们得先了解一下深浅拷贝,浅拷贝简单来说就是:只是对指针的拷贝,拷贝后和原来的指针指向同一块空间,如图:


    所以,浅拷贝其实存在很多问题:

        1.由于都指向同一块空间,所以,一旦其中一个对其内容做了更改,则所有对象都会发生变化,显然这并不是我们想要的。

        2.很容易造成同一块空间被释放两次,因为都指向同一块空间。

        3.很容易造成内存泄漏

    深拷贝即不止对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。



     深拷贝解决了浅拷贝存在的那些问题,但是如果每次都给对象开辟内存,但是不一定会进行更改,岂不是会浪费内存?所以写时拷贝出现了

那么写时拷贝是什么意思呢?

   顾名思义,就是在程序要进行写入操作是进行深度拷贝,否则进行浅拷贝,设置一个引用计数(与空间绑定在一起),当又有新指针指向这块空间时,引用计数+1,析构时,先检测引用计数是否为1,若为1则直接释放,否则,引用计数-1即可。有兴趣的读者可以验证一下,在Windows下,string是用深度拷贝的方式实现的,但是在Linux下,string是用写时拷贝的方式实现的。

2.写时拷贝string的部分实现:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<iostream>
#include<cstring>
using namespace std;

class String
{
	friend ostream &operator<<(ostream &os, const String & s);
public:
	String(char *str = "")
		:_str(new char [strlen(str) + 5])   //将引用计数器和字符串放在同一块空间
	{
		_str += 4;
		GetCount()=1;            //取到引用计数器的空间并赋为1.
		strcpy(_str, str);
	}
	~String()
	{
		Release();         //为增强代码的复用性,封装了一个释放空间的函数
	}
	String(const String & s)
		:_str(s._str)
	{
		GetCount()++;
	}
	String& operator=( String& s)
	{
		if (this != &s)        //判断是否自己给自己赋值
		{
			Release();
			_str = s._str;
			++GetCount();
		}
		return *this;
	}
	char &operator[](size_t index)    //写时,深度拷贝
	{
		if (GetCount() > 1)           
		{
			GetCount()--;
			char *tmp = new char[strlen(_str) + 5];
			strcpy(tmp+4, _str);
			_str = tmp+4;
			GetCount()++;
		}
		return _str[index];
	}
private:
	int& GetCount()            //得到引用计数空间并以引用的方式返回,方便计数器改变
	{
		return *(int *)(_str - 4);
	}
	void Release()
	{
		if (GetCount() == 0)
		{
			delete[](_str - 4);
		}
	}
private:
	char* _str;
};
ostream &operator<<(ostream &os, const String & s)
{
	os << s._str << "";
	return os;
}
void test1()
{
	String s1("hello");
	String s2(s1);
	String s3("world");
	s2 = s3;
}

void test2()
{
	String s("hello");
	s[2] = 'q';
	cout << s << endl;
}

int main()
{
	test1();
	test2();
	getchar();
	return 0;
}


    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值