【STL专题】深入探索C++之std::string:不止于字符串【万字详解】

欢迎来到CILMY23的博客

🏆本篇主题为:深入探索C++之std::string:不止于字符串

🏆个人主页:CILMY23-优快云博客

🏆系列专栏:Python | C++ | C语言 | 数据结构与算法 | 贪心算法 | Linux

🏆感谢观看,支持的可以给个一键三连,点赞关注+收藏。


✨写在前头: 

了解完模板和STL后,我们要开始研究std命名空间中的string,作为我们STL学习的开端,string对我们重新认识C语言中的字符串有很大意义。在上文中我们说过容器(Containers),容器是用来存储数据的对象,如数组、链表、树结构等。STL提供了多种类型的容器,本期我们将了解string类,虽然string并没有被归为容器,但它也和容器类似。


目录

string 

一、string的前瞻

1.1 C语言中的字符串

1.2 string的基本概念

☄️☄️文档阅读 

​编辑

☄️☄️信息翻译

☄️☄️总结

二、string类的常用接口

 💫String 类的默认成员函数

🍃构造函数(⭐)

🍃析构函数

 🍃赋值运算符重载

 💫String 类的容量操作

 🎈size(⭐),length,capacity,max_size

 🎈empty

 🎈clear(⭐)

 🎈reserve(⭐)

 🎈resize(⭐)

 🎈shrink_to_fit(⭐) 

💫string类对象的访问及遍历操作 

⛵⛵类对象的访问

🌠opertor[](⭐) 

🌠at

🌠back和front

⛵⛵string类的遍历

 🌠[](⭐) 

 🌠迭代器(⭐) 

 🌠 范围for

💫string类对象的修改操作 

1️⃣ push_back

 2️⃣ append

3️⃣ operator+=(⭐)

4️⃣ insert

5️⃣ assign

6️⃣ erase (⭐)

7️⃣replace

💫string类对象的字符串操作  

💧find(⭐)

💧rfind 

💧c_str

💧substr (⭐)

💫string类对象的非成员函数重载   

🌼swap(⭐) 

🌼operator+

🌼getline

🌼operator<< 和 operator>>

三、string类的接口一览图 


string 

一、string的前瞻

1.1 C语言中的字符串

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP(面向对象编程)的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问

 我写C语言字符串系列篇的时候还是深有体会的,稍不留神就越界访问导致出错,有时候还难排查出来。

1.2 string的基本概念

string 类是 C++ 标准库中的一部分,它提供了对字符序列的封装,使得字符序列的操作变得既简单又安全。

☄️☄️文档阅读 

我们来看看文档是怎么说的:文档的阅读网站我放在了文章末尾,在这里我分了两部分的文档基本阅读

🍀🍀图一: 

 🍀🍀图二:

☄️☄️信息翻译
  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信 息,请参阅basic_string)。
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits 和allocator作为basic_string的默认参数(根于更多的模板信息请参考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;

二、string类的常用接口

 💫String 类的默认成员函数

string的默认成员函数我们在这里主要看以下三部分: 

🍃构造函数(⭐)

 进入构造函数的文档界面,我们看到有七个构造函数,其中重点掌握的,也是最常用的,我在图片中已经标出来了。剩下的了解就差不多了。

在这里我们要了解第三个,前面两个很容易理解,但是第三个是什么呢?npos又是什么呢?

我们来看声明和定义,文档在底下给了我们的定义 

string (const string& str, size_t pos, size_t len = npos) 

 解析我在图片中标出来了,大家可以研究研究。

 substring constructor是指字串构造。

现在主要的问题是 npos 是个什么东西? 文档给我们提供了链接,我们可以点击查看(链接)

 

这里一看我们就知道了,原来 npos 是 size_t (无符号整数)的最大值,这就涉及原码反码和补码了(不懂的小伙伴可以看看链接)。 

-1 的补码是32个1,也就是2的32次方-1,但是string构造函数并不会开到这么多空间,所以就只会判定拷贝直到str的末尾。

🍭🍭实际操作 

写了这么多,我们来实际操作一下。在vs 2019上对这几个构造函数进行使用:记得包含头文件<string>

string s0;
string s1("CILMY23");
string s2(s1,2,3);
string s3(s2);//拷贝构造
string s4(s1, 3, string::npos);//从第三个位置开始,拷贝到str字符串末尾
string s5(10, '*');
string s6("CILMY23", 2);

结果如下: 

 

🍃析构函数

对析构函数我们不必关注太多,稍微看看就行

在学习的时候,我们知道析构函数的功能即可 

 🍃赋值运算符重载

在这里赋值运算符重载主要给了三种方式 

 这三种方式的实操如下:

🍭🍭实际操作 

string s7;

s7 = s2; //将s2拷贝给s7
s7 = "CILNY23";//将常量字符串赋值给s7
s7 = '*';//将单字符*赋值给s7

 结果如下:

 赋值运算符重载用的最多的还是前两种,一般第三种还是挺少用的。

 💫String 类的容量操作

string 的容量操作一共有以下操作:

 我们重点学习:size,empty,clear,reserve,resize

 🎈size(⭐),length,capacity,max_size

在string类中,sizelength是一样的,都是返回字符串的长度。,它们表示的是字符串中,有效字符的个数,而capacity表示的是容量,max_size,它返回 string 类型对象最多包含的字符数。也就是string类型支持的最大字符数,超过这个数,将无法支持,编译器会拋出 length_error 异常。

 我们知道在字符串的末尾是有\0的,在这里是不计入size和length的。

为什么这里会相同呢?

 这就不得不提及STL和String的先后问题了,其实是String比STL先出现的,所以String在刚刚的网站中我们是在Container中是找不到String的,但是它跟容器差不多,所以就增加了一个size接口,起初最先我们使用的是lengthsize()length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。 

说完了sizelength,我们接下来看看capacity

 

capacity返回的是开辟空间的大小,它是一个const成员函数,this指针指向的内容是不可以改变的 ,它和size是不一样的,有可能等于size,也可能比size还多

我们可以看一下在vs上它是如何扩容的, 

size_t sz = s1.capacity();
int n;
for (n = 0; n < 1000; n++)
{
	s1.push_back('*');

	if (sz != s1.capacity())
	{
		sz = s1.capacity();
		cout << "capacity changed->" << s1.capacity() << endl;
	}
		
}

结果如下:

我们可以看到它的扩容机制大概是按1.5倍来扩容的 

而g++底下的扩容机制是按照两倍扩容的。 

所以说具体的这些细节,是不确定的。 

 🍭🍭实际操作 

string s1("hello CILMY23");

cout << s1.size() << endl;
cout << s1.length() << endl;
cout << s1.capacity() << endl;
cout << s1.max_size() << endl;
cout << s1.npos << endl;

 结果如下:

但是我这里max_size可能是受到了系统或者编译器的限制,在我查阅很多文档后,都说它比npos还小1个,这里得考虑字符'\0'。所以最大长度是不

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值