0
点赞
收藏
分享

微信扫一扫

C++实现MyString拓展

心智的年轮 2022-03-16 阅读 22

MyString拓展

String的写时拷贝

class String
{
protected:
	struct StrNode
	{
		int ref;
		int len;
		int size;
		char data[];
	};
private:
	StrNode* pstr;
public:
	String(const char* p = NULL)
	{
		if (p != NULL)
		{
			int sz = strlen(p);
			pstr = (StrNode*)malloc(sizeof(StrNode) + sz * 2 + 1);
			pstr->ref = 1;
			pstr->len = sz;
			pstr->size = sz * 2;
			strcpy(pstr->data, p);
		}
	}
	~String()
	{
		if (pstr != NULL && --pstr->ref == 0)
		{
			free(pstr);
		}
		pstr = NULL;
	}
	String(const String& str) :pstr(NULL)
	{
		if (str.pstr != NULL)
		{
			pstr = str.pstr;
			pstr->ref += 1;
		}
	}
	String& operator=(const String& s)
	{
		if (this == &s)return *this;
		if (this->pstr != NULL && --this->pstr->ref == 0)
		{
			free(this->pstr);
		}
		this->pstr = s.pstr;
		if (this->pstr != NULL)
		{
			this->pstr->ref += 1;
		}
		return *this;
	}

	char& operator[](const int index)
	{
		if (pstr == NULL)exit(0);
		assert(index >= 0 && index <= this->pstr->len - 1);
		if (pstr->ref == 1)
		{
			return pstr->data[index];
		}
		else
		{
			int total = sizeof(StrNode) + pstr->size + 1;
			StrNode* newnode = (StrNode*)malloc(total);
			memmove(newnode, pstr, total);
			newnode->ref = 1;
			pstr->ref -= 1;
			this->pstr = newnode;
			return pstr->data[index];
		}
	}
	const char& operator[](const int index)const
	{
		return (*const_cast<String*>(*this))[index];
		//常方法直接进行返回
		//去常性 使得常方法调用普通方法
	}   //s1[2]; //s1.operator[](2); //operator[](&s1,2)
	
	ostream& operator<<(ostream& out)const
	{
		if (pstr != NULL)
		{
			out << pstr->data;
		}
		return out;
	}
};

ostream& operator<<(ostream& out, const String& s)
{
	s << out;
	return out;
}

int main()
{
	String s1("123456");
	String s2(s1);

	String s3("hello");
	String s4(s3);

	s1[0] = 'x';
	cout << s2 << endl;

	return 0;
}

在这里插入图片描述
在这里插入图片描述

当我们需要对公用数组的多个对象中的一个进行修改的时候,需要创建空间进行深拷贝,使其独立成为一个新的对象,在进行修改

在我们调用常方法的[]运算符重载时,会发生常方法无法调用普通方法而导致的无限调用自身,return (*this)[index];而我们通过强制的手段,将this指针改为非常性使得正确调用普通方法

移动拷贝与移动赋值

String(String&& s):pstr(NULL)
{
	this->pstr = s.pstr;
	s.pstr = NULL;
}
String& operator=(String&& s)
{
	if (this != &s)
	{
		if (pstr != NULL && --pstr->ref == 0) //释放原本的空间
		{
			free(pstr);
		}
		this->pstr = s.pstr;
		s.pstr = NULL;
	}
	return *this;
}

写时拷贝的改进

每当我们通过调用中括号重载时 operator[](),都会产生新的空间,即使我们不需要改写,仅仅是进行获取

接下来我们对其进行改进

char operator[](const int index) const //仅取值
{
	assert(pstr != NULL && index >= 0 && index <= pstr->len-1);
	return pstr->data[index];
}
void modify(const int index, const char ch)//修改函数
{
	assert(pstr != NULL && index >= 0 && index <= pstr->len - 1);
	if (pstr->ref > 1)
	{
		int total = sizeof(StrNode) + pstr->size + 1;
		StrNode* newnode = (StrNode*)malloc(total);
		memmove(newnode, pstr, total);
		newnode->ref = 1;
		pstr->ref -= 1;
		this->pstr = newnode;
	}
	pstr->data[index] = ch;
}

添加修改函数来实现修改的需求

String加法重载

	const String operator+(const String& s)const
	{
	    //处理字符串为空,或其中一个为空的情况
		if (this->pstr == NULL && s.pstr == NULL)
		{
			return String();
		}
		else if (pstr != NULL && s.pstr == NULL)
		{
			return *this;
		}
		else if (pstr != NULL && s.pstr == NULL)
		{
			return s;
		}
		else
		{
			int total = (pstr->len + s.pstr->len) * 2;
			StrNode* newsp = (StrNode*)malloc(sizeof(StrNode) + total + 1);
			strcpy(newsp->data, pstr->data);
			strcat(newsp->data, s.pstr->data);
			newsp->ref = 1;
			newsp->len = pstr->len + s.pstr->len;
			newsp->size = total;

			return String(newsp); //创建一个私有特殊的构造函数
		}
	}

String加等重载

String& operator+=(const String& s)
{
	if (this->pstr != NULL && s.pstr != NULL)
	{
		if (this->pstr->ref > 1)
		{
			int total = this->pstr->len + s.pstr->len;
			this->pstr->ref -= 1;
			char* tmp = this->pstr->data;
			this->pstr = (StrNode*)malloc(sizeof(StrNode) + total * 2 + 1);
			strcpy(this->pstr->data, tmp);
			strcat(this->pstr->data, s.pstr->data);
			this->pstr->ref = 1;
			this->pstr->len = total;				this->pstr->size = total*2;
		}
		else //仅一个对象共享内存
		{
			if (this->pstr->size >= this->pstr->len + s.pstr->len)
			{
				strcat(this->pstr->data, s.pstr->data); //将s连接至this后面
				this->pstr->len = this->pstr->len + s.pstr->len;
			}
			else
			{
				int total = this->pstr->len + s.pstr->len;
				this->pstr = (StrNode*)realloc(this->pstr, sizeof(StrNode) + total * 2 + 1);//将内存追加至目标大小
				strcat(this->pstr->data, s.pstr->data);
				this->pstr->len = total;
			}
		}
		return *this;
	}
	if (s.pstr == NULL)
	{
		return *this;
	}
	else if (pstr == NULL && s.pstr != NULL)
	{
		pstr = s.pstr;
		pstr->ref += 1; // 将原本s的值 给到了this 会多出一个引用计数
		return *this;
	}
}

在这里插入图片描述

举报

相关推荐

0 条评论