STL中string类基本概念及模拟实现

Posted 程序猿是小贺

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL中string类基本概念及模拟实现相关的知识,希望对你有一定的参考价值。

1. 标准库中的string类

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型。
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数。
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

总结:

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
  4. 不能操作多字节或者变长字符的序列。在使用string类时,必须包含#include头文件以及using namespace std;

2 string类的常用接口

C++中的string类,这里有你想了解的任何string类的东西,下面是简单的一小部分我截图了

1.构造方式

string()
string(const string& s)
string(const char*)

2.迭代器:

begin/end(正向迭代器)
rbegin()/rend反向迭代器

3.容量操作

resize(size_t n, char ch)
resize(size_t n)
reserve(size_t n):

注意:元素增多时可能会扩容、将元素个数减少时,容量不改变
扩容
1.n > old扩容---->开辟新空间拷贝元素释放旧空间
2.n < old缩小
n > 15:不会将容量缩小
n <= 15:将空间释放掉,直接使用内部固定大小的数组
sizeof(string):28字节
char* size_t size_t + 16个字符的数组

clear() //清空

4.元素访问操作
operator[+ at(index)
5.修改modify–修改string对象管理字符串的结构

6.特殊操作

c_str( find(char ch, size_t pos = 0) 
rfind(char ch, size_t pos = npos);

string:npos是string内部维护的一个静态成员变量
静态常量 size_t npos = -1;
size_t 的最大值
npos是一个静态成员常量值,对于size_t类型的元素具有最大可能值。
该值在string的成员函数中用作len(或sublen)参数的值时,表示“直到字符串的结尾”。 作为返回值,它通常用于表示没有匹配项。 此常量定义为-1值,因为size_t是无符号整数类型,因此它是此类型的最大可能表示值。

substr(size_t pos = o, size_t n = npos)

3. 浅拷贝与深拷贝

浅拷贝:也称值拷贝、位拷贝,只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以 当继续对资源进项操作时,就会发生了访问越界。要解决浅拷贝问题,引入了深拷贝。

class string
{
public:
 string(const char* str = "")
 {
 // 构造string类对象时,如果传递nullptr指针,认为程序非法,此处断言下
 if(nullptr == str)
 {
 assert(false);
 return;
 }
 
 _str = new char[strlen(str) + 1];
 strcpy(_str, str);
 }
 
 ~string()
 {
 if(_str)
 {
 delete[] _str;
 _str = nullptr;
 }
 }
private:
 char* _str;
};
void Teststring()
{
 string s1("hello bit!!!");
 string s2(s1);
}

深拷贝∶给每个对象独立分配资源,保证多个对象之间不会因共享资源而造成多次释放造成程序崩溃问题

4.模拟实现string类

模拟实现string,传统版

class String
{
public:
	//构造
	String(const char *str = "")
	{
		if (nullptr == str)
		{
			str = "";
		}
		//str是一个合法的字符串
		_str = new  char[strlen(str) + 1];
		strcpy(_str, str);
	}
	//拷贝构造,按照深拷贝的方式实现
	String(const String& s)
		:_str(new char[strlen(s._str) + 1])
	{
		//String tmp(s);//无限递归
		strcpy(_str, s._str);
	}
	//赋值运算符重载
	String& operator = (const String& s)
	{
		if (this != &s)
		{
			//1.申请新空间
			char *tmp = new char[strlen(s._str) + 1];
			//2.拷贝字符串
			strcpy(tmp, s._str);
			//3.释放旧空间
			delete[]_str;
			//4.使用新空间
			_str = tmp;
		}
		return *this;		
	}
	//析构
	~String()
	{
		if (_str)
		{
			delete[]_str;
			_str = nullptr;
		}
	}
private:
	char* _str;
};
void TestString1()
{
	String s1("hello");
	String s2(s1);
}
void TestString2()
{
	String s1("hello");
	String s2("world");
	s1 = s2;
}
int main()
{
	//TestString1();
	TestString2();
	return 0;
}

模拟实现string,深拷贝现代版

class String
{
public:
	//构造
	String(const char *str = "")
	{
		if (nullptr == str)
		{
			str = "";
		}
		//str是一个合法的字符串
		_str = new  char[strlen(str) + 1];
		strcpy(_str, str);
	}
	//拷贝构造,按照深拷贝的方式实现
	String(const String& s)
		:_str(nullptr)
	{
		//String tmp(s);  //无限递归
		String tmp(s._str);
		swap(_str, tmp._str);
	}

	//赋值运算符重载
	String& operator = (String s)
	{
		swap(_str, s._str);
		return *this;
	}

	//析构
	~String()
	{
		if (_str)
		{
			delete[]_str;
			_str = nullptr;
		}
	}
private:
	char* _str;
};

void TestString1()
{
	String s1("hello");
	String s2(s1);
}
void TestString2()
{
	String s1("hello");
	String s2("world");
	s1 = s2;
}
int main()
{
	TestString1();
	TestString2();
	_CrtDumpMemoryLeaks;  //检测内存是否泄露.vs中的一个函数
	return 0;
}

以上就是今天要学习的基本内容,当然有关于string类的只是远不止这些,在这里有你想了解到的string的很多内容,真心建议大家有时间的话都去看看,学习永无止境,梦想遥不可及,我们还需加倍努力!

以上是关于STL中string类基本概念及模拟实现的主要内容,如果未能解决你的问题,请参考以下文章

STL中string类基本概念及模拟实现

C++-string概念及实现

RxJava系列2(基本概念及使用介绍)

设计模式-基本概念及UML图

栈和队列的基本概念及操作

类的基本概念及self是什么东西?