文章目录
- String常用的接口(黑框标记的是常用接口)
- string类对象的反向遍历操作
- 第一种
- 第二种
- 容量
- string的扩容机制
String常用的接口(黑框标记的是常用接口)
string类对象的反向遍历操作
第一种
通过下表进行遍历
void TestString1()
{string s1("hello world");for (int i = s1.size(); i >= 0; i--){cout << s1[i] << " ";}cout << endl;
}
第二种
reverse_iterator
:
反向迭代器
rbegin
:
返回一个指向字符串最后一个字符的反向迭代器(即它的结尾)。
rend
:
返回一个反向迭代器,指向字符串第一个字符前面的理论元素(该元素被认为是字符串的反向结束)。
void TestString2()
{string s1("hello world");string::reverse_iterator rit = s1.rbegin();while (rit != s1.rend()){cout << *rit << " ";rit++;}cout << endl;
}
容量
szie
:
返回字符串的长度,以字节为单位。
lenth
:
返回字符串的长度,以字节为单位。
void TestString3()
{string s1("hello world");cout << s1.size() << endl;cout << s1.length() << endl;
}
没错你没有理解错,这两个接口作用完全一样,都是表示字符串中的字符数量。
至于原因:
主要是为了保持与C风格字符串处理函数的兼容性,因为在C语言中,字符串的长度是通过 strlen()
函数得到的,它返回的是字符串中的字符数量,不包括结尾的空字符 \0
。简而言之就是为了保持与C语言字符串处理函数的一致性。
max_size
:
返回字符串可以达到的最大长度。
void TestString4()
{string s1("hello world");cout << s1.max_size() << endl;
}
注:
max_size
的值取决于实现和系统资源。不同编译器或者不同平台的实现可能会有所不同
capacity
:
返回当前为字符串分配的存储空间的大小,以字节表示
void TestString5()
{string s1("hello world");cout << s1.capacity() << endl;
}
说到string的分配储存空间,就说一下string的扩容机制
string的扩容机制
首先我们看下main的代码:
void Viewcapacity()
{string s;size_t sz = s.capacity();cout << "capacity changed: " << sz << '\n';cout << "making s grow:\n";for (int i = 0; i < 100; i++){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed:" << sz << '\n';}}
}
我们可以看出第一次扩容是二倍扩容[ capacity是没包含‘\0’的,15+‘\0’=16 -> 31+‘\0’=32]
而之后都是1.5倍扩容
有意思的是在Linux下是这种情况:
我们可以看到是一直二倍进行扩容
在不同的操作系统和编译器下可能会有所不同,这主要是因为底层的内存分配策略和系统资源限制不同。
其实STL是一个规范,规范功能,没有规定实现细节
clear
:
清除字符串的内容,使其成为一个空字符串(长度为0个字符)。
void TestString6()
{string s1("hello world");cout << s1 << endl;cout << "capacity:" << s1.capacity() << endl;s1.clear();cout << s1 << endl;cout << "capacity:" << s1.capacity() << endl;
}
我们可以看出clear可以清除数据但是并没有销毁空间
那么有没有销毁空间的接口呢?
在C++11中新增了个这个接口:
shrink_to_fit
:
请求字符串减少其容量以适合其大小,就是缩容
那么
void TestString6()
{string s1("hello world xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");cout << s1 << endl;cout << "capacity:" << s1.capacity() << endl;s1.clear();cout << s1 << endl;cout << "capacity:" << s1.capacity() << endl;s1.shrink_to_fit();cout << s1 << endl;cout << "capacity:" << s1.capacity() << endl;
}
可见capacity缩小,之所以这样(hello world后面全是x)是因为我们现在可以理解为shrink_to_fit
缩不到0,至于原因简单来说:shrink_to_fit
函数的作用是让 std::string
的容量(也就是它最多能装多少字符)缩小到刚好能装下它当前有的字符数量。如果 std::string
里面有15个字符,那么调用 shrink_to_fit
后,它的容量就会缩小到刚好能装下这15个字符的大小。这样做可以节省内存,因为不再需要多余的空间来装更多的字符了。
reserve
:
请求更改容量请求将字符串容量调整为最多n个字符的计划大小更改,说白了就是扩容
详细来说:reserve()
是std::string
类的一个成员函数,它的作用是预先分配足够的内存空间,以便将来可以存储更多的字符,而不需要频繁地重新分配内存。当你知道std::string
将会增长到一定的大小时,你可以使用reserve()
来提前分配足够的空间。这样做可以减少内存分配的次数,提高程序的效率,因为频繁的内存分配和释放可能会导致性能下降。
void TestString7()
{string s1;s1.reserve(100);cout << "capacity:" << s1.capacity() << endl;
}
诶,我明明是开100个空间为什么是111?
这和扩容机制类似虽然reserve(100)
这个函数调用告诉 std::string
对象预先分配至少100个字符的空间。但是,std::string
的实际容量可能会比100大这也是因为底层的内存分配策略和系统资源限制不同。
注:reserve
只能扩容,比capacity
大才会起作用反之不会起作用
resize
:
将字符串的大小调整为n个字符的长度
当你调用 resize(n) 时,字符串的大小会被设置为 n ,并且如果字符串当前大小小于 n ,那么会在字符串末尾添加额外的空字符(‘\0’)来填充到新的大小。如果字符串当前大小已经大于或等于 n ,那么 resize() 会截断字符串,只保留前 n 个字符。
那么我们会有这三种情况:
1.n比size小(如图中插入10)
2.n比size大但是比capacity小(如图中插入20)
3.n比capacity还要大(如图中插入30)