C++实现string[]重载区分读写

string类型的最重要技术实现是引用计数和浅拷贝。

写时复制,读时共享,类似于fork()函数,来创建子进程。

temp  String::operator[](size_t idx)
{
	return temp(*this, idx);
}
//---------------------1------------------------

实现方法:

  • 1:将[]重载延时发动,通过传入一个对象的形式,把[]和=抽离开来
  • 2:遇到=重载,就是写操作,否则是读操作
  • 3:传递回一个中间对象temp,并且将temp的<<运算符重载,可以正常输出temp[x]

在这里插入图片描述

前面存放引用计数是因为,一旦string发生扩容,或者继续写入的时候,会造成引用计数存储的被覆盖。

//----------------------2--------------------------
char &operator=(char c)
	{
		if (*(int*)(this->m_String.c_str() - 4) > 1)
		{
			char *p = new char[strlen(this->m_String._pstr) + 5]() + 4;//往后偏移到数据指针
			strcpy(p, this->m_String._pstr);
			--*(int*)(this->m_String.c_str() - 4);//将引用计数--
			m_String._pstr = p;
			++*(int*)(this->m_String.c_str() - 4);//自成一派,引用计数为+1
			m_String.c_str()[m_index] = c;
		}
		return m_String.c_str()[m_index];//延时发动成功,返回单个字符即可
	}
//---------------------------3---------------------------
friend ostream& operator<<(ostream& os, const temp &rhs)
	{
		os << rhs.m_String._pstr[rhs.m_index];
		return os;
	}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B1A7wFnB-1622726488369)(C:%5CUsers%5CLenovo%5CDesktop%5Cmd%5C1622726460547.png)]

#include <string.h>
#include <iostream>
using namespace std;
class String;
class temp;
class String
{
	friend temp;
public:
	String()
		: _pstr(new char[5]() + 4)
	{
		cout << "String()" << endl;
		*(int *)(_pstr - 4) = 1;
	}

	String(const char *pstr)
		: _pstr(new char[strlen(pstr) + 5]() + 4)
	{
		cout << "String(const char *)" << endl;
		strcpy(_pstr, pstr);
		*(int *)(_pstr - 4) = 1;
	}
	String(const String &rhs)
		: _pstr(rhs._pstr)
	{
		cout << "String(const String &)" << endl;
		++*(int *)(_pstr - 4);
	}

	String &operator=(const String &rhs)
	{
		cout << "String &operator=(const String &)" << endl;

		if (this != &rhs)//1、自复制
		{
			--*(int *)(_pstr - 4);//2、释放左操作数
			if (0 == *(int *)(_pstr - 4))
			{
				delete[](_pstr - 4);
			}

			_pstr = rhs._pstr;//3、浅拷贝
			++*(int *)(_pstr - 4);
		}

		return *this;//4、返回*this
	}

	//s3[0] = 'H';
	temp operator[](size_t idx);

	~String()
	{
		cout << "~String()" << endl;
		--*(int *)(_pstr - 4);
		if (0 == *(int *)(_pstr - 4))
		{
			delete[](_pstr - 4);
		}
	}

	char *c_str() 
	{
		return _pstr;
	}

	int getRefCount() const
	{
		return *(int *)(_pstr - 4);
	}

	size_t size() const
	{
		return strlen(_pstr);
	}

	friend std::ostream &operator<<(std::ostream &os, const String &rhs);
	friend ostream& operator<<(ostream& os, const temp &rhs);
	
private:
	char *_pstr;
};

std::ostream &operator<<(std::ostream &os, const String &rhs)
{
	if (nullptr != rhs._pstr)
	{
		os << rhs._pstr;
	}
	return os;
}
class temp
{
public:
	temp(String& s, size_t idx);
	char &operator=(char c)
	{

		if (*(int*)(this->m_String.c_str() - 4) > 1)
		{
			char *p = new char[strlen(this->m_String._pstr) + 5]() + 4;//往后偏移到数据指针
			strcpy(p, this->m_String._pstr);
			--*(int*)(this->m_String.c_str() - 4);
			m_String._pstr = p;
			++*(int*)(this->m_String.c_str() - 4);
			m_String.c_str()[m_index] = c;
		}

		return m_String.c_str()[m_index];

	
	}
	friend ostream& operator<<(ostream& os, const temp &rhs)
	{
		os << rhs.m_String._pstr[rhs.m_index];
		return os;
	}
private:
	String &m_String;
	size_t m_index;
};
void test()
{
	String s1("hello");
	cout << "s1 = " << s1 << endl;
	printf("s1's address: %p\n", s1.c_str());
	printf("s1's RefCount = %d\n", s1.getRefCount());

	cout << endl;
	String s2 = s1;
	cout << "s1 = " << s1 << endl;
	cout << "s2 = " << s2 << endl;
	printf("s1's address: %p\n", s1.c_str());
	printf("s2's address: %p\n", s2.c_str());
	printf("s1's RefCount = %d\n", s1.getRefCount());
	printf("s2's RefCount = %d\n", s2.getRefCount());

	cout << endl;
	String s3("world");
	cout << "s3 = " << s3 << endl;
	printf("s3's address: %p\n", s3.c_str());
	printf("s3's RefCount = %d\n", s3.getRefCount());

	cout << endl << "执行s3 = s1操作" << endl;
	s3 = s1;
	cout << "s1 = " << s1 << endl;
	cout << "s2 = " << s2 << endl;
	cout << "s3 = " << s3 << endl;
	printf("s1's address: %p\n", s1.c_str());
	printf("s2's address: %p\n", s2.c_str());
	printf("s3's address: %p\n", s3.c_str());
	printf("s1's RefCount = %d\n", s1.getRefCount());
	printf("s2's RefCount = %d\n", s2.getRefCount());
	printf("s3's RefCount = %d\n", s3.getRefCount());

	cout << endl << "执行s3 = s1操作" << endl;
	s2[1] = 'H';
	cout << "s1 = " << s1 << endl;
	cout << "s2 = " << s2 << endl;
	cout << "s3 = " << s3 << endl;
	printf("s1's address: %p\n", s1.c_str());
	printf("s2's address: %p\n", s2.c_str());
	printf("s3's address: %p\n", s3.c_str());
	printf("s1's RefCount = %d\n", s1.getRefCount());
	printf("s2's RefCount = %d\n", s2.getRefCount());
	printf("s3's RefCount = %d\n", s3.getRefCount());
#if 1
	cout << endl << "对s3[0]进行读操作"<<s3[0] << endl;
	s3[0] = 'H';
	cout << s1[0] << endl;
	cout << "s1 = " << s1 << endl;
	cout << "s2 = " << s2 << endl;
	cout << "s3 = " << s3 << endl;
	printf("s1's address: %p\n", s1.c_str());
	printf("s2's address: %p\n", s2.c_str());
	printf("s3's address: %p\n", s3.c_str());
	printf("s1's RefCount = %d\n", s1.getRefCount());
	printf("s2's RefCount = %d\n", s2.getRefCount());
	printf("s3's RefCount = %d\n", s3.getRefCount());
#endif
}
int main(int argc, char **argv)
{
	test();
	return 0;
}

temp  String::operator[](size_t idx)
{
	return temp(*this, idx);
}

temp::temp(String & s, size_t idx)
	:m_String(s)
	,m_index(idx)
{
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值