c++--->string的细节加模拟实现string

  • namespace A
    {
    	class string
    	{
    	public:
    		//迭代器
    		typedef char* iterator;//string里的迭代器本质指针,以后迭代器就不一定是指针了
    		typedef const char* const_iterator;//const类型的迭代器
    		const_iterator begin()const
    		{
    			return _str;
    		}
    		iterator begin()
    		{
    			return _str;
    		}
    		iterator end()const
    		{
    			return _str + _size;
    		}
    
    		//构造
    		string(const char* s = " ")
    			:_size(strlen(s))
    			,_capacity(strlen(s))
    			,_str(new char[strlen(s)+1])
    		{
    			strcpy(_str, s);
    		}
    
    		void swap(string& s)           //这个是A::string里的swap
    		{
    			::swap(_size, s._size);    //这个调用的是全局的swap
    			::swap(_capacity, s._capacity);
    			::swap(_str, s._str);
    		}
    
    		//拷贝构造
    		/*string (const string& b)
    			:_str(new char[strlen(b._str) + 1])
    		{
    			strcpy(_str, b._str);
    		}*/
    		string(const string& s)
    			:_str(nullptr)        //这里必须初始化
    		{
    			string temp(s._str);//可能是这的问题
    			swap(temp);
    			//swap(_size, temp._size);//这里为啥不能用s.,因为参数是const类型的
    			//swap(_capacity, temp._capacity);
    			//swap(_str, temp._str);
    			//return *this;
    		}
    
    		//赋值运算符重载=
    		string& operator=(string s)
    		{
    			//swap(_size, s._size);
    			//swap(_capacity, s._capacity);
    			//swap(_str, s._str);
    			swap(s);
    			return *this;
    		}
    		//传统的=
    		//string& operator=(const string& b)
    		//{
    		//	if (this != &b)
    		//	{
    		//		delete[]this->_str;//先判断赋值双方是不是一个
    		//		_str = new char[strlen(b._str) + 1];
    		//		strcpy(_str, b._str);
    		//	}
    		//	return *this;
    		//}
    
    		//析构函数
    		~string()
    		{
    			delete[] _str;
    			_str = nullptr;
    			_size = 0;
    			_capacity = 0;
    		}
    		
    		//扩容
    		//开有效元素的个数并填充扩size
    		void resize(size_t size,char c='\0')
    		{
    			if (size < _size)
    			{
    				_str[size] = '\0';
    				_size = size;
    			}
    			else
    			{
    				if (size > _capacity)
    				{
    					reserve(size);
    				}
    				for (int i = _size; i < size; i++)
    				{
    					_str[i] = c;
    				}
    				_str[size] = '\0';
    				_size = size;
    			}
    		}
    		//单纯扩容扩capacity
    		void reserve(size_t capacity)
    		{
    			if (capacity > _capacity)
    			{
    				char* temp = new char[capacity+1];
    				strncpy(temp, _str,_size+1);        //有效字符包含\0,拷贝的是字符,如果字符中间有\0,就拷不进去
    				strcpy(temp, _str);    //用这个如果有效字符是\0考不下来,但是_size已经增加了,所以中间是随机值
    				delete[]_str;
    				_str = temp;
    				_capacity = capacity;
    			}
    		}
    
    		//曾
    		void push_back(char c)
    		{
    			if (_size == _capacity)
    			{
    				reserve(_capacity * 2);
    			}
    			_str[_size] = c;
    			_str[_size + 1] = '\0';
    			_size++;
    		}
    		void append(const char* str)
    		{
    			int len = _size + strlen(str)+1;  //这个是擦边扩容,扩的刚好方下有效字符串,但是容量没有\0的位置,加一个\0的位置
    			if (len > _capacity)              //strlen是错的,如果有效字符包含\0,就出错
    			{
    				reserve(len);
    			}
    			strcpy(_str + _size, str);
    			_size = len;
    		}
    		string operator+=(char c)
    		{
    			push_back(c);
    			return *this;
    		}
    		string operator+=(const char* str)
    		{
    			append(str);
    			return *this;
    		}
    		string& insert(size_t pos,char str)
    		{
    			assert(pos < _size);
    			if (_capacity == _size)
    			{
    				//reserve(2 * _capacity);//如果_capacity是0,就错了
    				reserve(_capacity == 0 ? 4 : 2 * _capacity);
    			}
    			//用变量
    			//int end = _size;
    			//while (end >=(int) pos)   //int 类型的变量和size_t类型的进行比较都会转成size_t
    			//{
    			//	_str[end+1] = _str[end];
    			//	end--;
    			//}
    			//用指针也行
    			char* end = _str + _size;
    			while (end >= _str + pos)
    			{
    				*(end + 1) = *(end);
    				end--;
    			}
    			_str[pos] = str;
    			_size++;
    			return *this;
    		}
    		string& insert(size_t pos, const char *str)
    		{
    			assert(pos < _size);
    			int len = strlen(str);
    			if (len +_size> _capacity)
    			{
    				reserve(len+_size);
    			}
    			char* end = _str + _size;
    			while (end >= _str + pos)
    			{
    				*(end + len) = *(end);
    				end--;
    			}
    			strncpy(_str + pos, str, len);
    			_size=len+_size;
    			return *this;
    		}
    		//删
    		string& erase(int pos, size_t amount = npos)
    		{
    			assert(pos >= 0);
    			assert(pos <= _size);
    			if (amount > _size)
    			{
    				_str[pos] = '\0';
    				_size = pos;
    			}
    			else
    			{
    				for (int i = pos+amount; i <= _size; i++)
    				{
    					_str[i-amount] = _str[i];
    				}
    			}
    			return *this;
    		}
    		//查
    		int find(char str, int pos=0)
    		{
    			for (int i = pos; i < _size; i++)
    			{
    				if (_str[i] == str)
    				{
    					return i;
    				}
    			}
    			return -1;
    		}
    		int find(const char* str, int pos=0) //直接传一个字符串是const类型的,要用const接收
    		{
    			const char* spot = strstr(_str + pos, str);
    			if (spot)
    			{
    				return spot - _str;
    			}
    			else
    			{
    				return npos;
    			}
    		}
    		bool operator<(const string& s)
    		{
    			if (strcmp(_str, s._str) >= 0)
    			{
    				return false;
    			}
    			return true;
    		}
    		bool operator>(const string& s)
    		{
    			if (strcmp(_str, s._str) <= 0)
    			{
    				return false;
    			}
    			return true;
    		}
    		bool operator<=(const string& s)
    		{
    			return !operator>(s);
    		}
    
    
    		bool operator>=(const string& s)
    		{
    			return !operator<(s);
    		}
    
    		bool operator==(const string& s)
    		{
    			if (strcmp(_str, s._str) == 0)
    			{
    				return true;
    			}
    			return false;
    		}
    
    		bool operator!=(const string& s)
    		{
    			return !operator==(s);
    		}
    		//获取大小
    		int size()const
    		{
    			return _size;
    		}
    		int capacity()
    		{
    			return _capacity;
    		}
    		//打印
    		char* C_str()
    		{
    			return _str;
    		}
    
    		//[]重载
    		const char& operator[](int v)const  //const类型的调这个
    		{
    			return _str[v];
    		}
    		char& operator[](int v)//这里就不能加const了,加了和上面就是相同的函数,不是重载函数
    		{
    			return _str[v];
    		}
    		void clear()
    		{
    			_size = 0;
    			_str[_size] = '\0';
    		}
    	private:
    		char* _str;
    		int _size;
    		int _capacity;
    		static const size_t npos;
    	};
    引用做参数和返回值能做到:如果做参数能在函数内部修改,如果做返回值,返回后还能修改.都能提高效率,减少拷贝
    • 并不是所有地方都能用引用返回:注意:只有当除了函数作用域后还存在的对象才能用引用返回,如果出了作用域对象被销毁了就只能用传值返回.
    • 传值返回回进行一次拷贝,1.4或者8自己考进寄存器,2.如果对象大,拷贝是考进上一个函数的栈帧
  • size_t类型和int类型的差异,size_t是无符号整型,int是有符号的.两个类似类型相比,int又被转成无符号的,size_t -1就是32亿多,注意循环的条件那,

  • getline(cin,s1);能把空格也放在s1里...重载流插入运算符重载,如果用in>>ch;当接收到空格或者换行时in就忽略调了,就一直死循环下去了.

  • const修饰在成员函数后面实际是修饰*this,本质是保护成员变量在这个函数体内不被改变,返回值无所谓

  • 函数前面和后面都加const,函数体内不能被改,返回值也不能被改,同时返回值也要拿const接收

  • 可读可写的要实现两个版本,一个全加const,另一个 一个const也不加

  • 是否设置有缘函数

  • string的大小(64位操作系统linux下8字节(只用一个指针)开辟一片空间前八个字节存容量和大小,自己实现的12字节,vs下28字节)
  • 扩容,往大扩,一次大概扩15个,编译器决定...往小扩,容量一直不变,直到容量缩小成15个,容量才会变回15..空间是好不容易申请的所以不释放,直到字符串能在string里数组(16个字节,有效15个)中存下,才释放空间.
  • string的拷贝;有内存开辟的情况用深拷贝.......浅拷贝时:引用计数浅拷贝+写实拷贝(了解,设计复杂,特殊情况下有缺陷),多个对象拷贝一个对象的数据后,指向同一个空间,引用计数一直加,析构的时候引用计数先减,等到减到0再释放空间.写实拷贝是,没有对象写的时候共用空间,有对象写的时候,自己拷贝一份数据,自己去写属于自己的数据.注意修改引用计数.
  • B();//匿名对象,生命周期是这一行.匿名对象当参数传给函数,不会构造两个和也不会拷贝构造,只拷贝构造一个真正的形参编译器的优化//f(B(2)):做参数只构造一个形参,//B bb = 3;构造B temp(3)加一个拷贝构造给bb,3构造一个匿名对象//B b=f()返回的时候只拷贝构造一次,f的返回值直接拷贝构造b.编译器优化//表达式连续的步骤中才有可能优化,优化的是减少构造临时的对象//string s2 = "hello";//隐式类型的转换,构造一个匿名对象拷贝给s2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值