基于引用计数与copy-on-write原理实现string

一:基本实现

#include "pch.h"
#include<iostream>
using namespace std;
#pragma warning(disable:4996)
class mystring
{
public:
	mystring(const char *tmpstr = ""):pstr(new stringvalue(tmpstr))
	{
		cout<<"mystring构造函数执行了"<<endl;
	}

	mystring(const mystring& tmp):pstr(tmp.pstr)
	{
		++pstr->refcount;
		cout << "mystring拷贝构造函数执行了" << endl;
	}

	mystring& operator=(mystring &tmp)
	{
		/*防止自己拷贝给自己*/
		if (this == &tmp)
		{
			return *this;
		}

		/*拷贝赋值运算符=右边的对象引用计数减一*/
		--pstr->refcount;
		if (pstr->refcount == 0)
		{
			delete pstr;
		}

		/*拷贝赋值运算符=右边的对象指向新的对象
		即:=左边的对象,然后引用计数加一,因为
		又有了一个新的对象指向该内存块*/
		pstr = tmp.pstr;
		pstr->refcount++;

		cout << "mystring拷贝赋值运算符执行了" << endl;
		return *this;
	}

	~mystring()
	{
		--pstr->refcount;
		if (pstr->refcount == 0)
		{
			delete pstr;
		}
		cout << "mystring析构函数执行了" << endl;
	}

private:
	struct stringvalue/*作为一个公共部分*/
	{
		char *str;
		size_t refcount;
		stringvalue(const char *tmpstr):refcount(1)
		{
			str = new char[strlen(tmpstr) + 1];
			strcpy(str, tmpstr);
			cout<<"stringvalue构造函数执行了"<<endl;
		}
		~stringvalue()
		{
			cout << "stringvalue析构函数执行了" << endl;
			delete []str;
		}
	};
private:
	stringvalue *pstr;
public:
	size_t use_count()
	{
		return pstr->refcount;
	}

};

int main(int argc, char **argv)
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF);//查看内存泄漏

	mystring s1 = "I love China";
	cout << s1.use_count() << endl;
	
	mystring s2(s1);
	cout << s1.use_count() << endl;
	cout << s2.use_count() << endl;

	mystring s3;
	s3 = s1;

	cout << s1.use_count() << endl;
	cout << s3.use_count() << endl;


	_CrtDumpMemoryLeaks();/*查看内存泄漏*/
	return 0;
}

在这里插入图片描述
二:拓展
拓展一:
//针对一添加几个成员函数,由于标准库当中的string还有[]操作,这里也实现一下

const char& operator[](int index) const/*不可修改*/
	{
		cout << "const重载运算符[]执行了" << endl;
		return pstr->str[index];
	}

	char& operator[](int index) /*可修改*/
	{
		cout << "非const重载运算符[]执行了" << endl;
		if (pstr->refcount > 1)/*说明有多个对象指向同一个内存*/
		{
			--pstr->refcount;
			pstr = new stringvalue(pstr->str);/*写时复制*/
		}
		return pstr->str[index];
	}

//编译器对于调用const[]还是非const[]判断不出来,它不知道你使用[]时到底时用于读还是写,所以编译器比较简单粗暴,统一调用的是非const

mystring s3;
cout << s3[0] << endl;
s3[0] = 'y';
cout << s3[0] << endl;

拓展二:

由于跨线程使用的原因,要加锁,这里点一下。
内部加锁:一般不建议内部加锁
外部加锁:由程序员自己操作

拓展三:通过指针修改mystring所指向字符串的内容

在这里插入代码片
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值