C++之string的底层简单实现!(七千字长文详解)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++之string的底层简单实现!(七千字长文详解)相关的知识,希望对你有一定的参考价值。

C++之string的底层简单实现!

string之私有成员变量

namespace MySTL

    class string
	
    private:
		char* _str;
		size_t _size;
		size_t _capacity;
		//这里capacity表示的是实际可以存的内存的大小!
        //也可以表示真实的内存大小!
        const static size_t npos = -1;
	;

string构造函数

string(const char* str = "")

	_size = strlen(str);
	_capacity = _size;
	_str = new char[_capacity + 1];
	strcpy(_str, str);

string的拷贝构造

string(const string& str)

	_str = new char[str._capacity + 1];
	strcpy(_str, str._str);
	_capacity = str._capacity;
	_size = str._size;

= 重载!

 string& operator=(const string& str)

	if (this == &str)
	
		char* temp = new char[str._capacity + 1];
		strcpy(temp, str._str);
        
		delete[] _str;//比起拷贝构造要多一步先把原来自己的空间释放掉!
		_str = temp;
        
		_capacity = str._capacity;
		_size = str._size;
	
	return *this;

string的析构函数

~string()

	_size = _capacity = 0;
	delete[] _str;
	_str = nullptr;

string的迭代器

typedef char* iterator;

begin

iterator begin()

	return _str;

end

iterator end()//迭代器的最后一个指向有效数据的下一位!

	return _str + _size;

string的const迭代器

typedef const char* const_iterator;

begin

const_iterator begin()const

	return _str;

end

const_iterator end()const

	return _str + _size;

size

size_t size()const

	return _size;

capacity

size_t capacity()const

	return _capacity;

[]重载!

char& operator[](size_t pos)

	assert(pos < _size);
	return _str[pos];


const char& operator[](size_t pos)const

	assert(pos < _size);
	return _str[pos];

reserve

void reserve(size_t n)

	char* temp = new char[n + 1];
	strcpy(temp, _str);
	delete[] _str;
	_str = temp;
	_capacity = n;

resize

void resize(size_t n, char ch = \\0)

	assert(n >= 0);
	if (n <= _size)
	
		_str[n] = \\0;
		_size = n;
	
	else if (n > _size && n <= _capacity)
	
		while (_size < n)
		
			_str[_size] = ch;
			_size++;
		
		_str[_size] = \\0;
	
	else
	
		reserve(n);
		while (_size < n)
		
			_str[_size] = ch;
			_size++;
		
		_str[_size] = \\0;
		_capacity = n;
	

插入类接口!

Push_Back

void Push_Back(char c)

	if (_size == _capacity)
	
	    size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
		reserve(newcapacity);
		_capacity = newcapacity;
	
	_str[_size] = c;//这是\\0的位置!
	_size++;
	_str[_size] = \\0;//最后记得加上\\0

append

void append(char c)

	Push_Back(c);

//插入单个的字符,逻辑是根Push_Back是一样的!
void append(const char* str)

	size_t len = strlen(str);
	if (_size + len > _capacity)
	
		reserve(_size + len);
	
	//strcat(_str, str);
	strcpy(_str + _size,str);
    //上面两种实现方式都可以!
    //strcpy已经吧\\0都拷贝到_str里面了
    _size += len;

//插入一个字符串,也要进行扩容!
//但是不能二倍扩容!因为不能保证二倍扩容的空间大小是足够的!

+=重载

string& operator+=(char c)

	Push_Back(c);
	return *this;

string& operator+=(const char* str)

	append(str);
	return *this;

insert

插入一个字符

插入一个字符串

erase

string& erase(size_t pos, size_t len = npos)

	size_t end = _size;
	if (len == npos || len >= _size - pos)
	
		_str[pos] = \\0;
		_size = pos;
	//当len不传值的时候,和len大于剩下空间的时候!
	else
	
		strcpy(_str + pos, _str + pos + len);
		_size -= len;
	
	return *this;

find

size_t find(char ch, size_t pos = 0)const

	assert(pos < _size);
	for (size_t i = pos; i < _size; i++)
	
		if (_str[i] == ch)
		
			return i;
		
	
	return npos;

size_t find(const char* str, size_t pos = 0)const

	const char* ptr = strstr(_str + pos, str);//要加pos是因为从pos的位置开始找的!
	if (ptr == nullptr)
	
		return npos;
	
	else
	
		return ptr - _str;
	


clear

void clear()

	_str[0] - \\0;
	_size = 0;

>>的重载!

ostream& operator<< (ostream& out, const string& str)

	for (size_t i = 0; i < str.size(); i++)
	
		out << str[i];
	
	return out;

<< 重载!

istream& operator >>(istream& in, string& str)

    str.clear();
	char ch;
	in >> ch;
	while (ch != \\n && ch !=  )
	
		in >> ch;
		str += ch;
	
	str += \\0;
	return in;

正确写法!

istream& operator >>(istream& in, string& str)

    str.clear();
	char ch;
	ch = in.get();
	while (ch != \\n && ch !=  )
	
		str += ch;
		ch = in.get();
	
	return in;

==最终优化版!==

istream& operator >>(istream& in, string& str)

    str.clear();//用来清空str保留的数据!
	char buff[128] =  \\0 ;
	char ch;
	ch = in.get();
	int i = 0;
	while (ch != \\n && ch !=  )
	
        if (i == 127)//留一个用来存放\\0    如果i == 128的话!会导致乱码!因为+=的底层是append,append是调用strcpy来实现的!strcpy是以\\0作为结尾的!
		
			i = 0;
			str += buff;
		
		buff[i++] = ch;
		ch = in.get();
	
	if (i > 0)
	
		buff[i] = \\0;//如果不加上这个的话会把后面原本的值都拷进去!
		str += buff;
	
	return in;

	//getline的实现原理就是把条件换成while (ch != \\n)

最终代码

namespace MySTL

	class string
	
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		
			return _str;
		
		const_iterator begin()const
		
			return _str;
		
		iterator end()
		
			return _str + _size;
		
		const_iterator end()const
		
			return _str + _size;
		

		string(const char* str = "")
		
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		

		~string()
		
			_size = _capacity = 0;
			delete[] _str;
			_str = nullptr;
		
		string(const string& str)
		
			_str = new char[str._capacity + 1];
			strcpy(_str, str._str);
			_capacity = str._capacity;
			_size = str._size;
		
		string& operator=(const string& str)
		
			if (this == &str)
			
				char* temp = new char[str._capacity + 1];
				strcpy(temp, str._str);
				delete[] _str;
				_str = temp;
				_capacity = str._capacity;
				_size = str._size;
			
			return *this;
		
		const char* c_str()const
		
			return _str;
		

		size_t size()const
		
			return _size;
		

		size_t capacity()const
		
			return _capacity;
		

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

		void reserve(size_t n)
		
			char* temp = new char[n + 1];
			strcpy(temp, _str);
			delete[] _str;
			_str = temp;
			_capacity = n;
		
		void resize(size_t n ,char ch = \\0)
		
			assert(n >= 0);
			if (n <= _size)
			
				_str[n] = \\0;
				_size = n;
			
			else if (n > _size && n <= _capacity)
			
				while (_size < n)
				
					_str[_size] = ch;
					_size++;
				
				_str[_size] = \\0;
			
			else
			
			
				reserve(n);
				while (_size < n)
				
					_str[_size] = ch;
					_size++;
				
				_str[_size] = \\0;
				_capacity = n;
			
		



		void Push_Back(char c)
		
			if (_size == _capacity)
			
				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newcapacity);
				_capacity = newcapacity;
			
			_str[_size] = c;
			_size++;
			_str[_size] = \\0;
		

		void append(char c)
		
			Push_Back(c);
		


		void append(const char* str)
		
			size_t len = strlen(str);
			if (_size + len > _capacity)
			
				reserve(_size + len);
			
			//strcat(_str, str);
			strcpy(_str + _size, str);
			_size += len;
		
		string& operator+=(char c)
		
			Push_Back(c);
			return *this;
		
		string& operator+=(const char* str)
		
			append(str);
			return *this;
		
		const char& operator[](size_t pos)const
		
			assert(pos < _size);
			return _str[pos];
		

		string& insert(size_t pos, char c)
		
			if (_size == _capacity)
			
				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newcapacity);
				_capacity = newcapacity;
			

			size_t end = _size + 1;
			while (end > pos)
			
				_str[end] = _str[end - 1];
				end--;
			
			_str[pos] = c;
			_size++;
			return *this;
		

		string& insert(size_t pos, const char* str)
		
			size_t len = strlen(str);
			if (_size + len > _capacity)
			
				reserve(_size + len);
			
			size_t end = _size + len;
			while (end >= pos + len)
			
				_str[end] = _str[end - len];
				end--;
			
			strncpy(_str + pos, str, len);
			_size += len;
			return *this;
		
		string& erase(size_t pos, size_t len = npos)
		
			size_t end = _size;
			if (len == npos || len >= _size - pos)
			
				_str[pos] = \\0;
				_size = pos;
			
			else
			
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			
			return *this;
		
		size_t find(char ch, size_t pos = 0)const
		
			assert(pos < _size);
			for (size_t i = pos; i < _size; i++)
			
				if (_str[i] == ch)
				
					return i;
				
			
			return npos;
		
		size_t find(const char* str, size_t pos = 0)const
		
			const char* ptr = strstr(_str + pos, str);
			if (ptr == nullptr)
			
				return npos;
			
			else
			
				return ptr - _str;
			

		
		void clear()
		
			_str[0] - \\0;
			_size = 0;
		
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		const static size_t npos = -1;
	
	;
	ostream& operator<< (ostream& out, const string& str)
	
		for (size_t i = 0; i < str.size(); i++)
		
			out << str[i];
		
		return out;
	

	istream& operator >>(istream& in, string& str)
	

		str.clear();
		char buff[128] =  \\0 ;
		char ch;
		ch = in.get();
		int i = 0;
		while (ch != \\n && ch !=  )
		
			if (i == 127)
			
				i = 0;
				str += buff;
			
			buff[i++] = ch;
			ch = in.get();
		
		if (i >= 0)
		
			buff[i] = \\0;
			str += buff;
		
		return in;
	


以上是关于C++之string的底层简单实现!(七千字长文详解)的主要内容,如果未能解决你的问题,请参考以下文章

C++ 之string类常用接口功能解析(7千字长文带你玩懂string!)

c++之构造函数,析构函数(五千字长文详解!)

c++之引用(五千字长文详解!)

初步认识c++之命名空间详解(千字长文带你刨析你命名空间的细节)

5千字长文,深度总结HashMap底层实现&面试题收藏

c++之类和对象——类的定义,存储方式,this指针!(五千字长文详解!)