string类的常见构造及容量操作

举报
跳动的bit 发表于 2022/06/11 10:29:54 2022/06/11
【摘要】 1、string类对象的常见构造(constructor) 函数名称功能说明string() —— 重点构造空的 string 类对象,即空字符串string(const char* s) —— 重点用 C-string 来构造 string 类对象string(size_t n, char c)string 类对象中包含 n 个字符 cstring(const string& s) ——...
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);

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。