C/C++的string

前段时间看了点东西,导致知识比较乱,最近打算把他们总结一下,首先就是C/C++的string。首先简单的回顾接口之后还将讨论一下深浅拷贝的问题。

string

C的函数库里也提供了很多对C风格字符串操作的函数,但是使用的时候还是会遇到很多问题内存泄漏,访问越界,覆盖等一系列的问题,而且还不符合面向对象的风格。所以C++引入了字符串类。

string的接口

这里我们主要列出修改字符串的接口:
有空了在写,自己查c++也可

resize() 和 reserve()的区别

reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。
  resize是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。
  再者,两个函数的形式是有区别的,reserve函数之后一个参数,即需要预留的容器的空间;resize函数可以有两个参数,第一个参数是容器新的大小,第二个参数是要加入容器中的新元素,如果这个参数被省略,那么就调用元素对象的默认构造函数。

深浅拷贝

浅拷贝 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
深拷贝 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。

实现String类

这里有一种现代写法,因为String是深拷贝所以,所以设计临界资源的管理。现代写法利用局部变量的声明周期解决了这方面的问题。下面给出实现:

#include <assert.h>

class String
{
public:
	typedef char* iterator;
	typedef const char* const_iterator;

	const_iterator begin() const
	{
		return _str;
	}

	const_iterator end() const
	{
		return _str + _size;
	}

	iterator begin()
	{
		return _str;
	}

	iterator end()
	{
		return _str + _size;
	}

	String(const char* str = "")
		:_str(nullptr)
		, _capacity(0)
	{
		_size = strlen(str);
		Reserve(_size);
		strcpy(_str, str);
	}

	// s2(s1)
	String(const String& s)
		:_str(nullptr)
		, _size(0)
		, _capacity(0)
	{
		String tmp(s._str);
		Swap(tmp); // tmp.Swap(*this);
	}

	// s1 = s3
	String& operator=(String s)
	{
		Swap(s);
		return *this;
	}

	// s1.Swap(s2)
	void Swap(String& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);

	}

	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
	}

	void PushBack(char ch)
	{
		/*if (_size == _capacity)
		{
		Reserve(_capacity * 2);
		}

		_str[_size] = ch;
		++_size;
		_str[_size] = '\0';*/

		Insert(_size, ch);
	}

	void Append(const char* str)
	{
		/*	size_t len = strlen(str);
			if (_size + len > _capacity)
			{
			Reserve(_size + len);
			}

			strcpy(_str + _size, str);
			_size += len;*/

		Insert(_size, str);
	}

	// s1 += 'c'
	String& operator+=(char ch)
	{
		PushBack(ch);
		return *this;
	}

	String& operator+=(const char* str)
	{
		Append(str);
		return *this;
	}

	void Insert(size_t pos, char ch)
	{
		assert(pos <= _size);

		if (_size == _capacity)
		{
			Reserve(_capacity * 2);
		}

		for (size_t i = _size; i >= pos; --i)
		{
			_str[i + 1] = _str[i];
		}
		_str[pos] = ch;
		_size++;
	}

	void Insert(size_t pos, const char* str);
	void Erase(size_t pos = 0, size_t len = npos);
	size_t Find(char ch, size_t pos = 0);
	size_t Find(const char* str, size_t pos = 0);
	bool operator<(const String& s)const;
	bool operator<=(const String& s)const;
	bool operator>(const String& s)const;
	bool operator>=(const String& s)const;
	bool operator==(const String& s)const;
	bool operator!=(const String& s)const;


	// s1 + 'c'
	String operator+(char ch) const 
	{
		String tmp(*this);
		tmp.PushBack(ch);
		return tmp;
	}

	String& operator+(const char* str)
	{
		String tmp(*this);
		tmp.Append(str);
		return tmp;
	}

	char* c_str() const
	{
		return _str;
	}

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

		return _str[pos];
	}

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

		return _str[pos];
	}

	size_t Size() const
	{
		return _size;
	}
	
	size_t Capacity() const
	{
		return _capacity;
	}

	void Reserve(size_t n)
	{
		if (n == 0 || n > _capacity)
		{
			//size_nt ewsize = (n + 7) & ( ~7);
			size_t newsize = n;
			if (n % 8 != 0)
				newsize = (n / 8 + 1) * 8;
			else
				newsize = n + 8;

			char* newstr = new char[newsize];
			if (_str)
				strcpy(newstr, _str);
			_str = newstr;
			_capacity = newsize - 1;
		}	
	}

	void Resize(size_t n, char ch = '\0')
	{
		if (n <= _size)
		{
			_size = n;
			_str[_size] = '\0';
		}
		else
		{
			Reserve(n);

			for (size_t i = _size; i < n; ++i)
			{
				_str[i] = ch;
				++_size;
			}
			_str[_size] = '\0';
		}
	}

private:
	char*  _str;
	size_t _size;
	size_t _capacity;

	static size_t npos;
};

size_t String::npos = -1;


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值