目录
前言
一.String的成员函数:
1.基本成员函数
代码实验:
实验结果:
类对象每次扩容后的capacity数据展示:
1.2. resize():调整字符串大小
1.3reserve():请求更改该对象的容量capacity值
代码实验:
前言
String是第一个我们在C++道路上要学习的STL容器,在上篇博客中,我们也已经大概的了解到了String类的由来——由于C语言中char类型的数组、字符串用的不够方便,所以创建了String类,之后就是学习了该类对象的创建方式和多种遍历方法,感兴趣的小伙伴们可以去看看:( C++之STL——String字符序列类(1)
那么在本文中,我们将继续学习有关String类的成员函数!
一.String的成员函数:
1.基本成员函数
其实,String类的底层是用的顺序表的形式实现的,物理结构上是一段连续的存储空间——数组,只不过这个数组只用于存储字符内容,所以该类并没有模板!既然是数组,那肯定有空间大小、空间的使用情况、最大容量等属性,那么为了体现类的封装性,设计者将这些基本属性都进行封装成了成员函数:
size() / length()——获取String类对象当前数据的总个数 ;
max_size()—— 获取String类对象所能存放数据最大容量,单位是个数
resize()——用于调整类对象的_size数据,这个会针对_size和形参做多种情况的处理
capacity()——获取String类对象当前容量的大小
reserve()——用于扩大类对象的存储容量,是一个常用的函数。
clear()——对String类对象的数据内容清空(注:只清理数组的size,不清理数组的capacity)
empty()——判断该数组当前是否为空
shrink_to_fit——使该对象的容量(capacity)和大小(size)相等,相当于缩小容,缩容是用时间换取空间,创建一块新空间,用新空间代替旧空间。所以该函数几乎不用。
代码实验:
#include<iostream>
using namespace std;
int main() {
string s1;
cout << s1.size() << endl;
cout << s1.length() << endl;
cout << s1.capacity() << endl;
cout << s1.max_size() << endl;
cout << s1.empty() << endl;
cout << "--------------------" << endl;
string s2 = "Hello World!!!!!!";
cout << s2.size() << endl;
cout << s2.length() << endl;
cout << s2.capacity() << endl;
cout << s2.max_size() << endl;
cout << s2.empty() << endl;
cout << "--------------------" << endl;
s2.clear(); //清空
cout << endl;
cout << s2.size() << endl; //size和length功能相同
cout << s2.length() << endl;
cout << s2.capacity() << endl; //判断容量,若超出容量则该函数会自动扩容
cout << s2.max_size() << endl; //最大字符量:21亿多
cout << s2.empty() << endl;
cout << "-----------------" << endl;
return 0;
}
实验结果:
结果分析:通过上图代码演示:String类对象s1初始化就为空,而类对象被创建的那一刻,底层数组会默认被分配15个字节大小的容量,该数组默认的最大容量有21亿字节之多。
相比较有内容的s2对象,它的初始化内容就超出了底层默认给出的15字节,那么String类会自动为该对象进行扩容。通过clear()函数的使用,我们印证了使用clear,并不会清理s2的capacity,它的值仍然为31,只是size被清理为了0。
类对象每次扩容后的capacity数据展示:
void Test1(){
string s; //创建空字符串
size_t sz = s.capacity(); //获取字符串的容量
cout << s.capacity() << endl;
cout << "making s grow:\n";
for (int i = 0; i < 100; ++i){
s.push_back('c'); //在for中插入数据字符c一百次
if (sz != s.capacity()){
sz = s.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
}
通过结果可知:默认情况下都是15字节大小的容量,而每当我们为该对象增加数据超过其容量时,会触发底层扩容机制,该对象的capacity会进行1.5——2倍左右的容量增大。
注:这只是VS编译器下的扩容机制,在其他平台下可能会有所不同!
在这些基本函数中,最重要的是resize()和reserve():
1.2. resize():调整字符串大小
resize()有两种用法,一种只是调整该对象字符串的大小,还有一种是在调整的基础上,设定剩余空间的内容数据。 一般情况下,只要不加第二参数,默认用的是void resize(size_t n);
该函数说白了就是把类对象存储的字符串大小调整为 n 个字符的长度。
1. 如果第一参数n设定的值小于当前字符串长度,则当前值将缩短为其第一个 n 个字符,删除第 n 个字符以外的字符;
2. 如果 n 大于当前字符串长度,则通过在末尾插入所需数量的字符以达到 n 大小来扩展当前内容。此外resize()有第二个参数c,如果指定了 c,则新元素初始化为 c 的副本,否则,它们是值初始化字符(空字符)。
情况1:
int main(){
string ss1 = "Hello World"; //共11个字符大小
//情况1:当n<size(字符串的当前长度)时:数据被删,且size缩小
ss1.resize(5); //n==5,仅保留字符串的前5个字符
cout << ss1 << endl; //那么ss1=="Hello",size会被改变,该字符串被删除部分数据
cout << ss1.size() << endl;
cout << ss1.capacity() << endl;
cout << "----------------------------" << endl;
ss1 = "Hello World";
//情况2:当size<n<=15(capacity首次的容量)时:该字符串会被增加数据,容量不变
ss1.resize(15); //n==15,字符串大小为11,会全部被保存,但还剩4个字符,那么都为'\0'
cout << ss1 << endl; //那么ss1=="Hello World ",size会被改变,
cout << ss1.size() << endl;
cout << ss1.capacity() << endl; //不变
cout << "----------------------------" << endl;
}
ss1="hello world"; 对ss1使用resize(5)后,意味着ss1的字符串内容变为了"hello",强行删减了ss1的数据内容—— n< size。
//情况3:当n>15(capacity首次的容量)时:该字符串会被增加数据+容量也被扩大
ss1 = "Hello World";
ss1.resize(25,'h'); //n==25,字符串大小为11,会全部被保存,剩下的字符全部用字符h代替
cout << ss1 << endl; //那么ss1=="Hello World ",不仅size会被改变,capacity也会变,
cout << ss1.size() << endl;
cout << ss1.capacity() << endl;
ss1的大小为11,resize设定的n值为25,25大于11,则发生扩容,且该字符串由于使用了resize函数的第二参数,所以"hello world"后面的内容全部赋值为字符h。
1.3reserve():请求更改该对象的容量capacity值
reserve在英文中的意思为:存储、保留。
函数的具体含义:请求使字符串容量适应计划的大小更改为最多 n 个字符。
如果 n 大于当前字符串容量,则该函数会导致容器将其容量增加到 n 个字符(或更大)。
在其他情况下,收缩字符串容量被视为非约束性请求:容器实现可以自由优化,否则,字符串的容量大于 n。
注:此函数对字符串长度size没有影响,并且无法更改其内容。
说白了该函数就是用来扩容的!
代码实验:
int main(){
string ss2 = "Made In China!";
ss2.reserve(50);
cout << ss2.size() << endl;
cout << ss2.capacity() << endl;
ss2.reserve(100); //
cout << ss2.size() << endl;
cout << ss2.capacity() << endl;
return 0;
}
结果:
为ss2字符串扩充容量50字节,由于ss2的size为14,capacity为15,扩容50后从15-->63字节大小,再次扩容后从63-->111字节,从中可以发现:ss2的size始终没变。
注:如果该对象的capacity为100,使用reserve(5),并不会导致capacity缩容!
设计reserve函数的原因就是因为我们之前在写顺序表等数据结构在堆区扩容的时候,会有代价(时间或空间上的代价);而使用reserve不会有空间上或时间上的浪费,利用reserve()可以提高插入数据的效率,避免增容带来的开销。相当实用!