手写string类

本文详细介绍了如何手写一个C++ string类,包括构造函数、拷贝构造函数、析构函数、拷贝赋值操作符、加法操作符、加等于操作符、等于操作符、下标访问操作符以及重载的流输出操作符。文章重点讨论了这些函数的设计和实现,特别是针对带指针类的深拷贝问题。
摘要由CSDN通过智能技术生成

1.题目:实现string类

包含构造函数、拷贝构造函数、析构函数、拷贝赋值
扩展:重载+、重载+=、重载==、重载[]、重载<<。

2.分析

(1)设计类

定义成员变量char *m_data;,使用char型指针变量存储字符串的首地址。
在这里插入图片描述
除了重载<<外,其他函数都是成员函数,而输出流不能定义为成员函数,为了可以访问私有变量m_data,我们使用友元函数。

class myString
{
   
public:
	myString(const char *str = 0);					//构造
	myString(const myString& str);					//拷贝构造
	myString& operator=(const myString& str);		//重载=
	myString operator+(const myString& str) const;	//重载+
	myString& operator+=(const myString& str) ;		//重载+=
	bool operator==(const myString& str) const;		//重载==
	char& operator[](int index);					//重载[]
	~myString();									//析构

	//friend istream& operator >> (istream &is, myString &str);//输入
	friend ostream& operator<<(ostream &os,const myString &str);//输出
private:
	char *m_data;
};

注意到myString这个类是带指针的类,所以我们一定要自己写拷贝构造、拷贝赋值、析构函数防止内存泄漏

(2)构造函数

首先思考什么时候调用构造函数:暂时能想到这两种情况myString smyString s1("hello")
我们可以在类中声明的构造函数为myString(const char *str = 0);如果是第一种情况,传入默认参数NULL;第二种传入“hello”字符串,需要注意不能更改字符串,所以需要加const
总结下:
①构造函数没有返回值;
②使用const防止传入的参数被改变。
③声明中给定一个默认实参,但是在定义中不能带默认实参
好了,下面开始写函数体,对于传入非空的参数,我们需要做的就是动态申请块内存,再把传入的字符串拷贝进去。

myString::myString(const char* pstr)
{
   
	if (pstr)
	{
   
		m_data = new char[strlen(pstr) + 1];
		strcpy(m_data, pstr);
	}
	else
	{
   
		m_data = new char[1];
		*m_data = '\0';
	}
}

这里稍微解释下字符串的存储,如下图字符串以'\0'结尾,而我们需要得知传入的字符串有多长才能进行内存分配。strlen这个函数用于计算字符串的长度,但是不包括末尾的'\0',所以我们把他加上1才是我们需要动态分配的内存空间。strcpy(m_data, pstr);函数用于把pstr指针指向的字符串拷贝到m_data指向的字符串。
在这里插入图片描述
那么如果传入的参数是NULL呢,我们直接分配一个字节的空间,再把指针指向的值设为字符串结束符'\0'即可。

(2)拷贝构造函数

之前我们说了带指针的类必须要自己写拷贝构造函数是因为直接使用默认拷贝构造会出现浅拷贝。
所谓浅拷贝就是只复制了字符串的地址给指针,使两个指针同时指向一块内存空间,如果删除分配的内存后,剩下的那么指针变为野指针。我们需要分配内存空间再拷贝实现深拷贝。
拷贝构造函数依旧是构造函数,没有返回值、加上const防止str被改变。函数体内部依旧是先分配空间、再拷贝。

myString::myString(const myString& str)
{
   
	m_data = new char[strlen(str.m_data) + 1];
	strcpy(m_data
  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是一个简单的手写字符串实现,可以用来存储和操作字符串: ```c++ #include <iostream> class String { public: // 构造函数 String() { length = 0; data = new char[length + 1]; data[0] = '\0'; } String(const char* str) { length = strlen(str); data = new char[length + 1]; strcpy(data, str); } // 拷贝构造函数 String(const String& other) { length = other.length; data = new char[length + 1]; strcpy(data, other.data); } // 析构函数 ~String() { delete[] data; } // 重载赋值运算符 String& operator=(const String& other) { if (this != &other) { delete[] data; length = other.length; data = new char[length + 1]; strcpy(data, other.data); } return *this; } // 重载下标运算符 char& operator[](int index) { return data[index]; } const char& operator[](int index) const { return data[index]; } // 获取长度 int getLength() const { return length; } // 获取字符串 const char* getData() const { return data; } private: int length; char* data; }; int main() { String str1("Hello"); String str2 = str1; String str3; str3 = str2; std::cout << str1.getData() << std::endl; std::cout << str2.getData() << std::endl; std::cout << str3.getData() << std::endl; str2[0] = 'h'; std::cout << str2.getData() << std::endl; return 0; } ``` 上面这个实现只是一个简单的示例,实际上字符串的实现非常复杂,还需要考虑内存分配、动态扩容、编码方式等问题。在实际开发中,我们通常会使用标准库提供的字符串(如 C++ 中的 std::string)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值