C++小工修炼之路Ⅹ(string类)

浅拷贝如何解决:

  1. 深拷贝----让每个对象都拥有自己独立的资源—拷贝的不是对象本身的内容,而是对象管理资源中的内容
    a传统版解决办法,对产生对象的函数都进行深拷贝的操作
    b.现代版的解决办法,代码量少,提高了代码的复用率
    2.在浅拷贝的基础上,加上引用计数的方法,再加上写时拷贝,就大概可以实现浅拷贝的问题

但是不建议写这种写是拷贝的代码,因为在所有的进行写操作或者,push_back操作的代码中都有可能需要进行空间的分离,并且在单线程下面还好,多线程下又有安全问题。所以,还是别写了,知道就行了。

//模拟实现简单的string类
//关于memset()函数:memset函数是按照字节来设置元素的假如你要设置的是int类型的数组,那么不好意思设置不了
class string
{
  
  	friend ostream& operator<<(ostream& _cout, const string& p);
 public:
  typedef char* iterator;   //迭代器
 public:
 	 string(char* str = "")
 	{
   		if (str == nullptr)
    		str = "";
   		_size = strlen(str);
   		_capacity = strlen(str);
   		_str = new char[strlen(str) + 1];
   		strcpy(_str, str);
  	}
  	string(const char s, int n)
  	{
   		_size = n;
   		_capacity = n;  //这里的容量没有+1,也就是说没有算最后的'\0',这一切都是为了遵循,string本来的面貌
   		_str = new char(n + 1);
   		for (int i = 0; i < n; ++i)
    			_str[i] = s;
   		_str[n] = '\0';
  	}
  	string(const string& p)
  	 :_str(p._str)
  	 , _size(p._size)
  	 , _capacity(p._size)  //按理来说这里给出的空间的大小应该是p._capacity但是害怕p中有很大的容量,但是p中的有效元素却只有几个的情况下,所以直接按照size+1的大小来赋值,等到容量不够再扩容
  	{
  		 _str = new char[p._size + 1];
  		 strcpy(_str, p._str);
  	}
  	string& operator= (const string& p)
  	{
  		 if (this != &p)
   		{
    			delete[] _str;
    			_str = new char[strlen(p._str) + 1];
    			strcpy(_str, p._str);
    			_size = strlen(p._str);
    			_capacity = strlen(p._str);
   		}
   		return *this;
  	}
  	char& operator[](int x)const
  	{
   		assert(x < _size);
   		return _str[x];
  	}
  	char& operator[](int x)
  	{
   		assert(x < _size);
   		return _str[x];
  	}
  	~string()
  	{
   		if (_str)
   		{
    			delete[] _str;
    			_str = nullptr;
   		}
  	}
  /
  	int size()const
  	{
   		return _size;
  	}
  	int capacity()const
  	{
   		return _capacity;
  	}
  	bool empty()const
  	{
   		return (_size == 0);
  	}
  //
  	void resize(int newsize, char c)
  	{
   		int oldsize = _size;
   		if (oldsize < newsize)  //如果之前空间的有效长度小于你现在要扩展到的有效长度,那么就先看是否需要扩容
   		{
    			if (_capacity < newsize)  //如果需要扩容
    			{
     				reserve(newsize);
    			}
    			memset(_str + _size, c, newsize - oldsize);  //扩完容再填充
   		}
   		_size = newsize;   //最后无论哪种情况都会走到下面
   		_str[_size] = '\0';
  	}
  	void reserve(int size)
  	{
   		if (_capacity < size)
   		{
    			char* temp = new char[size + 1];
    			strcpy(temp, _str);
    			delete[] _str;
    			_str = temp;
    			_capacity = size;
   		}
  	}
  /
  	void push_back(char ch)
  	{
  		 if (_capacity == _size)
  		 {
  			  tow_capacity();
  		 }
  	 	_str[_size++] = ch;
  	 	_str[_size] = '\0';
  	}
  	string& operator+=(char ch)
  	{
   		push_back(ch);
   		return *this;
  	}
  	string& operator+=(char* ch)
  	{
   		while (((size_t)_size + strlen(ch)) > (size_t)_capacity)   //这里我转size_t纯属是为了消除警告:无符号与有符号不匹配
   		{
    			tow_capacity();
   		}
   		_str = strcat(_str, ch);
   		_size = _size + strlen(ch);
   		return *this;
  	}
  /
  	int find(char c)
  	{
   		for (int i = 0; i < _size; ++i)
   		{
    			if (c == _str[i])
     			return i;
   		}
   		return npos;
  	}
  	int find(char* c)
  	{
   		int flag = 0;
   		int i;
   		for (i = 0; i < _size; ++i)
   		{
    			if (c[0] == _str[i])
    			{
     				for (int j = i; j < strlen(c)&&j<_size; ++j)
     				{
      					if (c[j] != _str[j])
      					{
       						flag = 1;
       						break;
      					}
     				}
     				if (flag != 1)
      					return i;
    			}
    			flag = 0;
   		}
   		return npos;
  	}
  	int rfind(char c)
  	{
   		for (int i = _size - 1; i >= 0; --i)
   		{
    			if (c == _str[i])
     				return i;
   		}
   		return npos;
  	}
  	int rfind(char* c)
  	{
   		int flag = 0;
   		int i;
   		for (i = _size - 1; i >= 0; --i)
   		{
    			if (c[0] == _str[i])
    			{
     				for (int j = i; j < strlen(c) && j<_size; ++j)
     				{
      					if (c[j] != _str[j])
      					{
       						flag = 1;
       						break;
      					}
     				}
     				if (flag != 1)
      					return i;
    			}
    			flag = 0;
   		}
   		return npos;
  	}
  	string(char* begin,char* end)
  	{
   		_size = end - begin;
   		_capacity = _size;
   		_str = new char[_size + 1];
   		strncpy(_str, begin, _size);
  	}
  	string substr(int pos = 0,int end = npos)   //为了写这种方法还要专门给出一种构造函数,为的就是临时对象在离开作用域时候就被销毁
  	{
   		if (end == npos)
    		end = _size;
   		string strtemp(_str + pos, _str + pos + (end - pos+ 1));  //截取的区间长度,+1的原因是你举个例子试试就知道了
   		return strtemp;
  	}
  	const char* c_str()const
  	{
   		return _str;
  	}
  /
  	iterator begin()
  	{
   		return _str;
  	}
  	iterator end()
  	{
   		return _str + _size;
  	}
 private:
  	void tow_capacity()    //检测是否需要扩容
  	{
   		reserve(_capacity * 2);
  	}
 private:
  	char* _str;
  	int _size;
  	int _capacity;
  	static int npos;
 };
 int string::npos = -1;
 ostream& operator<<(ostream& _cout, const string& p)
 {
  	for (int i = 0; i < p._size; ++i)
  	{
   		_cout << p[i];
  	}
  	return _cout;
 }
 void test()
 {
  	string s1("123456");
  	string s2(s1);
  	string s3;
  	s3 = s2;
  	cout << s1 << endl;
  	cout << s2 << endl;
  	cout << s3 << endl;
  	cout << s2.capacity() << endl;
  	s2.reserve(10);
  	cout << s2.capacity() << endl;
  	s2.resize(15, '!');
  	cout << s2 << endl;
  	s2.push_back('w');
  	cout << s2 << endl;
  	s2 += 'o';
  	cout << s2 << endl;
  	s2 += "rld";
  	cout << s2 << endl;
  	s2 += "大河向东流呀!天上的星星参北斗呀!说走咋就走呀,你有我有全都有呀!";
  	cout << s2 << endl;
  	cout << s2.find('o') << endl;
  	cout << s2.rfind('o') << endl;
  	cout << s2.find("world") << endl;
  	cout << s2.rfind("world") << endl;
  	cout << s2.find("hello") << endl;
  	cout << s2.rfind("hello") << endl;
  	cout << s2.substr(15, 19) << endl;
 }	

在自定义类型中,加入想要使用范围for那么就必须给出begin()和end()两个函数,不然就没有办法使用,

	iterator begin()
  	{
   		return _str;
  	}
  	iterator end()
  	{
   		return _str + _size;
  	}
  	类私这样的函数,就是得到首位地址的函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值