STL —— string(终)

目录

1. swap() 函数的模拟实现

2. find() 函数的模拟实现

3. substr() 函数的模拟实现 

4. operator==()的重载模拟实现

5. << 和 >> 重载的模拟实现

6. getline() 的重载

7. 拷贝构造的现代写法

8. 赋值重载的现代写法


本片文章还是主要讲解 string 类中剩余几个函数的模拟实现:

1. swap() 函数的模拟实现

在C++库中就有swap()函数的实现,但是为什么要在string类中也要实现一个swap()函数呢?

我们可以先看一下库中的实现逻辑:

template <class T> void swap ( T& a, T& b )
{
  T c(a); a=b; b=c;
}

这里可以看到如果对内置类型,它会调用一次 拷贝构造、两次赋值重载、一次析构,而且都是深拷贝,这样的效率就会大大增加,虽然可以实现swap()的功能,但是一般不推荐使用,所以会在库中自己实现。

因此我们可以自己实现一个 swap() 函数,只要对内置类型进行交换即可:

void swap(string& str)
{
    std::swap(_str, str._str);
	std::swap(_size, str._size);
	std::swap(_capacity, str._capacity);
}

 除此之外,为了防止调用算法库的swap(),我们可以写一个全局的swap():

void swap(string& x, string& y)
{
	x.swap(y);
}

2. find() 函数的模拟实现

查找字符的模拟实现:

size_t find(char ch, size_t pos = 0) const
{
	for (size_t i = pos; i < _size; ++i)
	{
		if (_str[i] == ch)
		{
			return i;
		}
		else
		{
			return npos;
		}
	}
}

查找字符串的模拟实现,可以用strstr()函数来完成,查找成功strstr会返回查询到的位置的指针, 查找失败则会返回空,因此要两个指针相减得到下标:

size_t find(const char* ch, size_t pos = 0) const
{
	// 字符串匹配
	const char* p = strstr(_str, ch);
	if (p)
	{
		return p - _str;
	}
	else
	{
		return npos;
	}

}

3. substr() 函数的模拟实现 

取子串的操作从pos位置开始,取len个,代码如下:

string substr(size_t pos = 0, size_t len = npos)
{
	string sub;
	if (len >= _size - pos)
	{
		for (size_t i = pos; i < _size; ++i)
		{
			sub += _str[i];
		}
	}
	else
	{
		for (size_t i = pos; i < pos + len; ++i)
		{
			sub += _str[i];
		}
	}
	return sub;
}

4. operator==()的重载模拟实现

这里就只实现==的重载,其他的重载只需要复用即可。

d31b517f14da4c5999e306d3f90318de.png

在库中重载是在全局中实现的,主要是为了实现 const char* 和 string 类型的比较,这里模拟实现就不在全局中实现了:

bool operator==(const string& s)
{
	int ret = strcmp(_str, s._str);
	return ret == 0;
}

5. << 和 >> 重载的模拟实现

<< 的重载比较简单,注意重载成全局的就可以了:

ostream& operator<<(ostream& _out, const string& str)
{
    for (size_t i = 0; i < str.size(); ++i)
    {
		_out << str[i] << " ";
	}
	_out << endl;
	return _out;
}

cin 读不到' '或者'\n',要用get()获取

  istream& operator>>(istream& in, string& s)
	{
		s.clear();

		char ch;
		//in >> ch;
		ch = in.get();
		char buff[128];
		size_t i = 0;
		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			// [0,126]
			if (i == 127)
			{
				buff[127] = '\0';
				s += buff;
				i = 0;
			}

			ch = in.get();
		}

		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;
	}

6. getline() 的重载

和>>类似:

  istream& getline(istream& in, string& s)
    {
		s.clear();

		char ch;
		//in >> ch;
		ch = in.get();
		char buff[128];
		size_t i = 0;
		while (ch != '\n')
		{
			buff[i++] = ch;
			// [0,126]
			if (i == 127)
			{
				buff[127] = '\0';
				s += buff;
				i = 0;
			}

			ch = in.get();
		}

		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;
	}

7. 拷贝构造的现代写法

这个是拷贝构造的正常的写法:

  • 先动态开辟一块内存,并把str._str中的数据拷贝到其中;
  • 让_str指向ch指向的空间
  • _size 和 _capacity 分别赋值
string(const string& str)
{
	char* ch = new char[str._capacity + 1];
	strcpy(ch, str._str);
	_str = ch;
	_size = str._size;
	_capacity = str._capacity;
}

现代写法:

  • 新建一个tmp对象用str._str初始化;
  • 然后再和this进行交换就可以了。
string(const string& str)
{
	string tmp(str._str);
	swap(tmp);
}

8. 赋值重载的现代写法

这个是赋值重载的正常的写法:

  • 新构建一块空间并把str中的值拷贝到其中;
  • 释放掉this->_str指向的空间;
  • 让this->str 指向这块空间;
  • 给this->_size 和 this->_capacity 赋值
string& operator=(const string& str)
{
	if (this != &str)
	{
		_size = str._size;
		_capacity = str._capacity;
		char* tmp = new char[_capacity + 1];
		delete[] _str;
		strcpy(tmp, str._str);
		_str = tmp;
	}

	return *this;
}

现代写法:

  • 新建一个tmp对象用str拷贝构造;
  • this和tmp进行交换;
  • 因为局部变量出作用域会自动调用析构函数,所以这里不需要自己重新写一份delete[] tmp._str 释放掉this原来指向的空间,如果写了delete,记得把tmp._str 制空;
string& operator=(const string& str)
{
	string tmp(str);
	swap(tmp);
	return *this;
}

还有更简单的写法:

因为这里是传值传参,会自动调用拷贝构造,就不需要我们自己手动写一个tmp的拷贝构造了。

string& operator=(string str)
{
	swap(str);
	return *this;
}

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值