String类的模拟实现---String类的构造、拷贝构造、析构函数以及赋值运算符重载等

通过动手实现String类的构造、拷贝构造、赋值运算符重载以及析构函数

以下分别包括传统写法和现代写法:
传统写法每一步都通过申请空间,资源清理、释放空间;
现代写法理解为进行了偷懒,通过调用构造函数、拷贝构造来实现。

class String
{
public:
	String(const char* str = "")
		:_size(strlen(str))
		,_capacity(_size)
		,_data(new char[strlen(str) + 1])
	{
		strcpy(_data, str);
	}
	void Swap(String& str)
	{
		swap(_size, str._size);
		swap(_capacity, str._capacity);
		swap(_data, str._data);
	}
private:
	//有效字符个数
	size_t _size;
	//容量:最大的存放字符的个数
	size_t _capacity;
	char* _data;
};

拷贝构造函数的传统写法与现代写法:

拷贝构造函数的传统写法:
String类的构造函数需要用到深拷贝,首先要知道什么是深拷贝?深拷贝与浅拷贝的区别是什么?
首先清楚析构函数的作用,先进行资源清理,再进行空间释放。
例如:通过char* pr = new int; 动态申请了一块整形空间,pr指针指向该空间。在使用完成之后要调用析构函数进行空间释放,包括两部分:
资源清理:就是将动态申请的整型空间释放(该空间在堆上)
空间释放:将pr指针的指向置空
浅拷贝:只是将指针指向了该资源,相当于两个指针(拷贝和被拷贝)指向了同一份资源,在进行空间释放的时候会进行二次释放。
深拷贝:拷贝指针通过申请新的空间,并将资源拷贝过来。相当于两个指针分别指向两个资源,这样在进行空间释放时不会出现二次释放问题。

	//传统写法:深拷贝:拷贝对象的内容 + 对象的资源
	String(const String& str)
		:_size(0)
		, _capacity(0)
		,_data(new char[strlen(str._data) + 1])
	{
		//拷贝资源
		strcpy(_data, str._data);
	}

拷贝构造函数的现代写法:

	//拷贝构造:现代写法 --> 复用拷贝的逻辑
	// 借助构造函数在创建局部对象时,进行空间申请 + 内容拷贝
	// 通过交换成员的执行,最终达到拷贝构造的目的
	String(const String& str)
		:_size(0)
		, _capacity(0)
		, _data(nullptr)
	{
		String tmp(str._data);
		Swap(tmp);
	}

赋值运算符重载的传统写法与现代写法:

赋值运算符重载的传统写法:

//传统写法:赋值运算符重载
	String& operator=(const String& str)
	{
		if (this != &str)
		{
			//释放原有的资源空间
			delete[] _data;
			//开新的资源空间
			_data = new char[strlen(str._data) + 1];
			//拷贝内容
			strcpy(_data, str._data);
		}
		return *this;
	}

赋值运算符重载的现代写法1:

	//现代写法1:调用构造函数
	String& operator=(const String& str)
	{
		String tmp(str._data);
		Swap(tmp);
		return *this;
	}

赋值运算符重载的现代写法2(主要):


	//现代写法2:调用拷贝构造
	// 借助拷贝构造完成:进行空间申请 + 内容拷贝
	// 借助局部对象的析构函数完成当前对象原有资源的释放
	String& operator=(String str)
	{
		Swap(str);
		return *this;
	}

现代写法:

class String
{
public:
	//String迭代器
	//实现:字符指针
	typedef char* iterator;
	typedef const char* const_iterator;

	iterator begin()
	{
		//第一个元素的位置
		return _data;
	}
	const_iterator begin() const
	{
		//第一个元素的位置
		return _data;
	}
	iterator end()
	{
		//最后一个元素的下一个位置
		return _data + _size;
	}
	const_iterator end() const
	{
		//最后一个元素的下一个位置
		return _data + _size;
	}
	//构造函数
	String(const char* str = "")
		:_size(strlen(str))
		,_capacity(_size)
		,_data(new char[strlen(str) + 1])
	{
		strcpy(_data, str);
	}
	//拷贝构造:现代写法 --> 复用拷贝的逻辑
	// 借助构造函数在创建局部对象时,进行空间申请 + 内容拷贝
	// 通过交换成员的执行,最终达到拷贝构造的目的
	String(const String& str)
		:_size(0)
		, _capacity(0)
		, _data(nullptr)
	{
		String tmp(str._data);
		Swap(tmp);
	}
	//析构函数
	~String()
	{
		if (_data)
		{
			delete[] _data;
			_data = nullptr;
			_size = _capacity = 0;
		}
	}
	//交换
	void Swap(String& str)
	{
		swap(_size, str._size);
		swap(_capacity, str._capacity);
		swap(_data, str._data);
	}
	//扩容
	void reserve(size_t n)
	{
		//只增加容量
		if (n > _capacity)
		{
			//1.开空间
			char* tmp = new char[n + 1];
			//2.拷贝
			strcpy(tmp, _data);
			//释放原有空间
			delete[] _data;

			//更新成员
			_data = tmp;
			_capacity = n;
		}
	}

	const char* c_str() const
	{
		return _data;
	}
	
	//现代写法2:调用拷贝构造
	// 借助拷贝构造完成:进行空间申请 + 内容拷贝
	// 借助局部对象的析构函数完成当前对象原有资源的释放
	String& operator=(String str)
	{
		Swap(str);
		return *this;
	}

	size_t size() const
	{
		return _size;
	}

	size_t capacity() const
	{
		return _capacity;
	}

	char& operator[](size_t pos)
	{
		assert(pos < _size);
		return _data[pos];
	}

	const char& operator[](size_t pos) const
	{
		assert(pos < _size);
		return _data[pos];
	}

	void append(const char* str)
	{
		//1.检查容量
		int len = strlen(str);
		if (_size + len >= _capacity)
		{
			reserve(_size + len);
		}
		//2.插入
		memcpy(_data + _size, str, sizeof(char) * len);
		//3.更新
		_size += len;
		_data[_size] = '\0';
	}
	
	void pushBack(const char ch)
	{
		if (_size == _capacity)
		{
			size_t newC = _capacity == 0 ? 15 : 2 * _capacity;
			reserve(newC);
		}
		_data[_size] = ch;
		++_size;

		_data[_size] = '\0';
	}

	//插入一个字符串
	String& operator+=(const char* str)
	{
		append(str);
		return *this;
	}
	//插入一个String对象
	String& operator+=(const String& str)
	{
		append(str._data);
		return *this;
	}
	String& operator+=(const char ch)
	{
		pushBack(ch);
		return *this;
	}
	void insert(size_t pos, const char& ch)
	{
		//检查位置的有效性
		assert(pos <= _size);
		//1.检查容量
		if (_size == _capacity)
		{
			size_t newC = _capacity == 0 ? 15 : 2 * _capacity;
			reserve(newC);
		}
		//2.移动元素:从后向前
		size_t end = _size + 1;
		while (end > pos)
		{
			_data[end] = _data[end - 1];
			--end;
		}
		//3.插入
		_data[pos] = ch;
		//更新
		_size++;
	}
	void insert(size_t pos, const char* ptr)
	{
		//检查位置的有效性
		assert(pos <= _size);
		//1.检查容量
		int len = strlen(ptr);
		if (_size + len > _capacity)
		{
			reserve(_size + len);
		}
		//移动元素
		size_t end = _size + len;
		while (end > pos + len - 1)
		{
			_data[end] = _data[end - len];
			--end;
		}
		//3.插入
		//for (int i = 0; i < len; ++i)
		//{
		//	_data[i + pos] = ptr[i];
		//}
		memcpy(_data + pos, ptr, sizeof(char) * len);
		//更新
		_size++;
	}
	void erase(size_t pos, size_t len = npos)
	{
		assert(pos < _size);
		//从pos开始,删除剩余的所有元素
		if (len == npos || pos + len >= _size)
		{
			_size = pos;
			_data[_size] = '\0';
		}
		else
		{
			//从前向后,每一个待移动的元素统一向前移动len个位置
			size_t start = pos + len;
			//[pos + len, size]
			while (start <= _size)
			{
				_data[start - len] = _data[start];
				++start;
			}
			_size -= len;
		}
	}

	size_t find(const char& ch, size_t pos = 0)
	{
		for (size_t i = pos; i < _size; ++i)
		{
			if (_data[i] == ch)
				return i;
		}
		//未找到或者位置越界
		return npos;
	}
	size_t find(const char* ptr, size_t pos = 0)
	{
		assert(pos < _size);
		char* ptr = strstr(_data + pos, ptr);
		if (ptr)
		{
			return ptr - _data;
		}
		return npos;
	}
	
	String substr(size_t pos, size_t len = npos)
	{
		assert(pos < _size);
		if (len == npos || pos + len >= _size)
		{
			String str(_data + pos);
			return str;
		}
		else
		{
			char* newC = new char[len];
			memcpy(newC, _data + pos, sizeof(char) * len);
			newC[len] = '\0';
			return String(newC);
			delete[] newC;
		}
	}


private:
	//有效字符个数
	size_t _size;
	//容量:最大的存放字符的个数
	size_t _capacity;
	char* _data;

	static const size_t npos;
};

const size_t String::npos = -1;

String operator+(const String& str1, const String& str2)
{
	String str = str1;
	str += str2;
	return str;
}

String operator+(const char* str1, const String& str2)
{
	String str(str1);
	str += str2;
	return str;
}

String operator+(const char ch, const String& str2)
{
	String str = str2;
	str += ch;
	return str;
}
bool operator<(const String& str1, const String& str2)
{
	int ret = strcmp(str1.c_str(), str2.c_str());
	if (ret < 0)
		return true;
	return false;
}

bool operator==(const String& str1, const String& str2)
{
	int ret = strcmp(str1.c_str(), str2.c_str());
	if (ret == 0)
		return true;
	return false;
}
// > :!( <= )

ostream& operator<<(ostream& out, const String& str)
{
	//不是按照c分割的字符串形式输出
	for (const auto& ch : str)
	{
		out << ch;
	}
	return out;
}

istream& operator>>(istream& in, String& str)
{
	char ch;
	//while ((ch = cin.get()) != EOF)
	while ((ch = getchar()) != EOF)
	{
		if (ch == ' ' || ch == '\n')
			break;
		//尾插
		str += ch;
	}
	return cin;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值