string类的常见构造及容量操作
1、string类对象的常见构造
(constructor) 函数名称 | 功能说明 |
---|---|
string() —— 重点 | 构造空的 string 类对象,即空字符串 |
string(const char* s) —— 重点 | 用 C-string 来构造 string 类对象 |
string(size_t n, char c) | string 类对象中包含 n 个字符 c |
string(const string& s) —— 重点 | 拷贝构造函数 |
#include<string>
#include<iostream>
using namespace std;
//大概原理
template<class T>
class basic_string
{
T* _arr;
int _size;
int _capacity;
};
//typedef basic_string<char> string;
int main()
{
string s1;
string s2("hello");
string s3("比特");
string s4(10, 'a');
string s5(s2);
//对于string它重载了流提取和流插入等,这里就可以直接用
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
cout << s5 << endl;
//赋值 ———— 深拷贝
s1 = s5;
cout << s1 << endl;
}
📝说明
basic_string ❗
string s1; || string s2(“hello”); ❗
通过调试我们发现 s1 虽然是无参的,但并不是啥都没有,且会在第一个位置放一个 \0。
2、string类对象的容量操作
函数名称 | 功能说明 |
---|---|
size —— 重点 | 返回字符串有效字符长度 |
length | 返回字符串有效字符长度 |
capacity | 返回空间总大小 |
empty —— 重点 | 检测字符串释放为空串,是返回 true,否则返回 false |
clear —— 重点 | 清空有效字符 |
reserve —— 重点 | 为字符串预留空间 |
resize —— 重点 | 将有效字符的个数改成 n 个,多出的空间用字符 c 填充 |
#include<string>
#include<iostream>
using namespace std;
void test_string1()
{
//1、size | length
string s1("hello world");
cout << s1.size() << endl;
cout << s1.length() << endl;
cout << "----------cut----------" << endl;
//2、max_size
string s2;
cout << s1.max_size() << endl;
cout << s2.max_size() << endl;
cout << "----------cut----------" << endl;
//3、capacity
cout << s1.capacity() << endl;
cout << "----------cut----------" << endl;
//4、resize
string s3("hello world");
cout << s3.size() << endl;
cout << s3 << endl;
//s3.resize(20);//n大于当前的字符串的长度且没有指定c,所以hello world\0\0\0\0...
//s3.resize(5);//n小于当前的字符串的长度, 它会删除掉从n开始的这些字符
s3.resize(20, 'x');//n大于当前的字符串的长度且指定c,所以hello worldxxxx...
cout << s3.size() << endl;
cout << s3 << endl;
cout << "----------cut----------" << endl;
//5、reserve
string s4("hello world");
s4.reserve(20);
cout << s4 << endl;
cout << s4.size() << endl;
cout << s4.capacity() << endl;
s4.reserve(10);
cout << s4 << endl;
cout << s4.size() << endl;
cout << s4.capacity() << endl;
cout << "----------cut----------" << endl;
//6、clear | empty
string s5("hello world");
cout << s5 << endl;
cout << s5.empty() << endl;;
s5.clear();
cout << s5 << endl;
cout << s5.empty() << endl;
cout << "----------cut----------" << endl;
//7、shrink_to_fit 暂且不演示
}
void test_string2()
{
string s;
size_t sz = s.capacity();
cout << "making s grow:\n" << sz << endl;
for(int i = 0; i < 500; ++i)
{
s.push_back('c');
if(sz != s.capacity())
{
sz = s.capacity();
cout << "capacity changed:" << sz << '\n';
}
}
cout << "----------cut----------" << endl;
}
int main()
{
test_string1();
test_string2();
return 0;
}
📝说明
size || length ❗
两者的功能相同,一般我们比较常用的是 size。
对于 string 是在 STL 这个规范前被设计出来的,因此在 Containers 下并没有 string:
早期说要算字符串字符的长度,所以早期提供的接口就叫 length,至于后面要加 size 的原因是后面增加了 map、set 这样的树,所以用 length 去表示它的数据个数就不合适了。
max_size ❗
它也是早期设计比较早的,属于一个没用的接口 —— 从操作系统中获取最大的长度。本意是想告诉你这个字符串最大你能定义多长, 这个接口在设计的时候其实不好实现,它没有办法标准的去定义这个接口,因为它有很多不确定的因素。所以它这个地方是直接给你 2^32^ ,也就是 4G。所以没什么价值,以后再遇到就直接跳过了。
capacity ❗
对于 string 对象而言,如果 capacity 是 15,意味着它有 16 个字节的空间,因为有一个位置是 \0 的。对于 capacity 它会随着字符串的大小而增容,这里默认是 15。
resize ❗
resize 的前者版本可以让字符串的长度变成 n;后者可以让字符串的 n 个长度变成 c。
如果 n 是小于当前的字符串的长度, 它就会缩减到 n 个字符,删除掉从 n 开始的这些字符。
如果 n 是大于当前的字符串的长度,通过在末尾插入尽可能多的内容来扩展当前内容,倘若指定了 c,则新元素被初始化为 c 的副本,否则它们就是值初始化字符 (空字符 \0)。
对于 s3.resize(20); s3[19] 是有效位置,因为对于 operator[] 里它会 assert(pos < _size)。
reserve ❗
请求 capacity。
注意这里不是你要多少 capacity 它就给多少 capacity,它在增容时还要对照不同编译器下自己的增容规则,最终容量不一定等于字符串长度,它可能是相等的,也可能是更大的。
如果 n 大于当前字符串的 capacity,那么它会去扩容。
如果 n 小于当前字符串的 capacity,这里跟不同的平台有关系。文档里是这样说的:其他情况下 (小于或等于),有可能它会缩容(开一块新空间,将数据拷贝,释放原有空间),也有可能不对当前空间进行影响,只是变换 capacity 的值。已证,VS 和 Linux 下不会缩容,STL 的标准也是这样规定的,这是实现 STL 的人决定的。
对于 s4.reserve(20); s4[19] 是无效位置,因为对于 operator[] 里它会 assert(pos < _size)。
string 增容是怎么增的 ❓
test_string2():
可以看到 Windows VS 下初始容量是 15 ,除了第一次,其余的大概是以 1.5 倍增容。
g++ ???
可以看到在不同的编译器下增容规则也不同,Linux g++ 下初始容量是 0,其余是以 2 倍增容的。
clear | empty ❗
清理字符串 | 判空字符串
resize 和 reserve 有什么价值 ❓
对于 resize,既要开空间,还要对这些空间初始化,就可以用 resize —— s.resize(20, ‘x’);
对于 reserve,明确知道需要多大空间的情况,可以提前把空间开好,以减少增容所带来的代价 —— s.reserve(500);
- 点赞
- 收藏
- 关注作者
评论(0)