C++(12):String类型

一、普通String类型

#include<assert.h>
//string类型
class String
{
	char* str;  //new  FILE *fp   thread(要重写拷贝和赋值,防止出现浅拷贝和浅赋值)
	String(char* s, int)
	{
		str = s;
	}
public:
	String(const char* s = nullptr) 
	{
		if (s != nullptr)
		{
			int len = strlen(s) + 1;
			str = new char[len];
			strcpy_s(str, len, s); //len是str开辟的空间长度
		}
		else
		{
			str = new char[1]; //仅指向一个字节
			this->str[0] = '\0'; //一定让他不为空,指向指向'\0'的一个空串
			//否则赋值,拷贝等,都要考虑四种情况,谁为不为空
			//eg:s1 NULL s2 "defe"
			//this->str = '\0';是将其置为空指针 
		}
	}
	~String()
	{
		if (str != nullptr)
		{
			delete[] str;
		}
		str = nullptr;
	}
	String(const String& s) //浅拷贝
	{
		//str = s.str; //共享资源,共享内存空间,会有重复释放的问题
		if (s.str != nullptr) //深拷贝
		{
			int len = strlen(s.str) + 1;
			str = new char[len];
			strcpy_s(str, len, s.str); //len是str开辟的空间长度
		}
	}
	String& operator = (const String& s) 
	{
		if (this!= &s)
		{
			//str = s.str;  //浅赋值
			delete[] str;  //深赋值
			int len = strlen(s.str) + 1;
			str = new char[len];
			strcpy_s(str, len, s.str);
		}
		return *this;
	}

	//移动构造:是资源的移动(减轻对堆区不断开辟释放的过程)
	String(String&& s)
	{
		str = s.str;
		s.str = nullptr;
	}
	//移动赋值
	String& operator=(String&& s)
	{
		if (this != &s)
		{
			delete[] str;
			str = s.str;
			s.str = nullptr;
		}
		return *this;
	}
	String operator+(const String& s) const
	{
		int total = strlen(this->str) + strlen(s.str) + 1;
		char* sp = new char[total];
		strcpy_s(sp, total, this->str);
		strcat_s(sp, total, s.str);

		//return String(sp) //调动构造产生一个临时对象,sp指向的空间就没有释放掉
		return String(sp, 1); //构建的临时对象的str将指向sp,将此对象赋给s3,资源移动
	} //对象+对象

	String operator+(const char* s) const //对象+变量
	{
		return *this + String(s);
	}
	String& operator+=(const String& s)
	{
		char* tmp = this->str;
		int total = strlen(tmp) + strlen(s.str) + 1;
		str = new char[total];
		strcpy_s(str, total, tmp);
		strcat_s(str, total, s.str);
		delete[] tmp; //tmp是原来str指向的资源
		return *this;
	} //s1 += s2
	String& operator+=(const char* s) //对象+=变量
	{
		return *this += String(s);
	}
	char& operator[] (const int index) const
	{
		assert(index >= 0 && index < strlen(this->str));
		return str[index];
	}
	const char& operator[] (const int index) const
	{
		assert(index >= 0 && index < strlen(this->str));
		return str[index];
	}
	ostream& operator<<(ostream& out) const
	{
		out << str;
		return out;
	} //s1<<cout; s1.operator<<(cout);operator<<(&s1,cout)
};

//设为全局函数,放入类中作为成员函数,参数列表省略了this指针,将变为3个参数
String operator+(const char* s, const String& st) //变量+对象
{
	return String(s) + st;  
}

String fun()
{
	String tmp("nswubd");
	return tmp;
}
ostream& operator<<(ostream& out, const String& s)
{
	s << cout;
	return cout;
}

int main()
{
	//String s1("wejbfwue");
	//String s2("dneide");
	//String s3(s1);

	String s1 = fun(); //构建的临时对象就是s1,移动赋值

	String s2("tulun"); 
	s2 = fun(); //深拷贝,tmp赋给临时对象,析构掉tmp,把临时对象赋给s2,把临时对象的资源给s2

	String s1("dheudh");
	s1 = std::move(s2); //当没写赋值语句时,缺省的移动赋值(不好用,要重写):是将字符串拷贝到s1所指向的空间,不会删除s2的资源,将内容直接拷贝
	
	String s4("wbfuwf");
	String s5("ejiwdewdw");
	s4 = s5; //调用普通的赋值语句,因为s5有名字,不能进行右值引用
	
	String s6; //s6中放的是‘\0’
	s6 = s4 + s5;

	s4 += s5;

	cout << s1 << endl; //输出

	return 0;
}

写赋值函数时都要考虑四种情况:
not not
not nullptr
nullptr not
nullptr nullptr
二、字符数组为柔性数组的String

class String
{
	//柔性数组
	struct StrNode
	{
		int len; //字符串的长度
		int size; //字符串的空间大小
		int ref; //引用计数
		char data[]; //柔性数组, 定义在最后
	};
private:
	StrNode* str;
	String(StrNode* s)
	{
		str = s;
	}
public:
	String(const char* s = nullptr): str(nullptr)
	{
		if (s != nullptr)
		{
			int len = strlen(s) + 1;
			str = (StrNode*)malloc(sizeof(StrNode) + 2 * len);  
			if (str == nullptr) exit(EXIT_FAILURE);
			str->len = len;
			str->size = 2 * len;
			str->ref = 1;
			strcpy_s(str->data, 2 * len, s);
		}
	}
	~String()
	{
		if (str != nullptr && -- this->str->ref == 0)
		{
			free(this->str);
		}
		str = nullptr;
	}
	String(const String& s) :str(s.str)
	{
		if (str != nullptr)
		{
			str->ref += 1;
		}
	}
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			if (str != nullptr && --str->ref == 0)
			{
				free(str);
			}
			str = s.str;
			if(str != nullptr)
			{
				str->ref += 1;
			}
		}
		return *this;
	} //s1 =s2(四种情况)

	//移动
	String(String&& s)
	{
		if (str != nullptr && --str->ref == 0)
		{
			free(str);
		}
		str = s.str;
		s.str = nullptr;
	}
	String& operator=(String&& s)
	{
		if (this != &s)
		{
			if (str != nullptr && --str->ref == 0)
			{
				free(str);
			}
			str = s.str;
			s.str = nullptr;
		}
		return *this;
	}
	String operator+(const String& s) const
	{
		//先开size
		int total = 1;
		if (str != nullptr) total += str->len;
		if (s.str != nullptr) total += s.str->len;
		StrNode* sp = (StrNode*)malloc(sizeof(StrNode) + 2 * total);
		
		if (sp == nullptr) exit(EXIT_FAILURE);
		if (str != nullptr) strcpy_s(sp->data, 2 * total, str->data);
		if (s.str != nullptr) strcat_s(sp->data, 2 * total, s.str->data);

		//设置StrNode的变量的值
		sp->len = total - 1;
		sp->size = 2 * total;
		str->ref = 1;
		return String(sp);
	} //四种情况

};
int main()
{
	String s1("iewbd");
	String s2("iewbciwebc");
	String s3;
	String s4(s1);
	String s5(s2);
	s3 = s1 + s2;
	//s3 = s1 + "neonwoi";
	//s3 = "oenw" + s1;
	s1 += s2;
	//s1 += "iedi";
	return;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值