STL.string(上)


由于string创始初期没有参照导致的冗余问题,这里没办法完全的进行的总结,所以只会列出一些常用的。

string类

string是表示字符串的字符串类
在这里插入图片描述
这里出现这么多不同的string的原因是编码表的不同。string => UTF-8、u16string => UTF-16、u32string => UTF-32。
该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
不能操作多字节或者变长字符的序列。
在这里插入图片描述

string类构造

在这里插入图片描述

int main()
{
	string s1;//默认构造1
	string s2("hello world!");//拷贝构造2
	string s3 = "hello world!";//const char*隐式类型转换为string 先构造再拷贝构造被优化成拷贝构造  4
	string s4(s3, 6, 3);//substring 3
	cout << s4 << endl;
	string s5(s3, 6, 13);//太少的话取到末尾
	cout << s5 << endl;
	string s6(s3, 6);//不给的话,自动赋值-1,32亿9千万,极值
	cout << s6 << endl;
	string s7(s2, 3);//对s2的第三个字符开始向后复制 5
	string s8(5,'x');//在s8中填充5个x 6
	
}

在这里插入图片描述

string类对象的容量操作

在这里插入图片描述
在这里插入图片描述

size和length

size 和length 功能是重叠的,原因是string过早,有些冗余。一般都使用size!
在这里插入图片描述

max_size

极值跟系统资源有关系,所以并没有什么实际用处。
在这里插入图片描述

append

添加进入一个字符串,一般不用push_back 和append ,而是使用 operator+= 。

在这里插入图片描述
在这里插入图片描述

小总结下size、capacity、append、operator+=

在string尾部追加字符时,s.push_back( c ) / s.append(1, c) / s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

int main()
{
	string s1("hello world");
	cout << s1.size() << endl;
	cout << s1.length() << endl;//俩者并无差别,发展历程length先出现
	cout << s1.max_size() << endl;//最大申请数量,意义不大
	cout << s1.capacity() << endl;//实际上是16字符,但是\0不计入

	s1.push_back(' ');
	s1.push_back('!');
	cout << s1 << endl;

	s1.append("yes");
	cout << s1 << endl;
	cout << "_______________________" << endl;
	s1 += ' ';
	s1 += '!';
	s1 += "yesyes";//实际我们使用+=多一点
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述

这里需要注意s1.capacity是15个字节,但是后面是有一个’\0’,capacity并没有将’\0’算入其中,所以实际上是16个字节。
至于为什么是16字节,这与编译器的底层逻辑相关,不同编译器的大小不同,在后面附录1会详细讲。

resize

在这里插入图片描述

resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_tn, char c)用字符c来填充多出的元素空间。
注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

resize 是 扩容+初始化,如果数量比size小,那么会删除数据,但是不会修改capacity!
因为缩容是不支持原地缩容,都是异地缩容,由于缩容需要释放空间,所以会先开辟新空间,然后拷贝,再释放空间,会产生很大的资源消耗,所以一般不会进行缩容

 int main()
{
	// 扩容
	string s1("hello world");
	s1.reserve(100);
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	// 扩容+初始化
	string s2("hello world");
	s2.resize(100, 'x');
	cout << s2.size() << endl;
	cout << s2.capacity() << endl;

	// 比size小,删除数据,保留前5个
	s2.resize(5);//缩容,但是不建议使用缩容,因为缩容是异地缩容
	cout << s2.size() << endl;
	cout << s2.capacity() << endl;

	return 0;
}

在这里插入图片描述

reserve

在这里插入图片描述

前提:知道需要多少空间,可以帮助我们提前开空间,减少扩容,提升效率。

对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。
reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。

int main()
{
	// 观察扩容情况  -- 1.5倍扩容
	string s;
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	cout << "capacity changed: " << sz << '\n';
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

在这里插入图片描述
在这里插入图片描述

初识迭代器

在这里插入图片描述

附录

1. vs下string结构的说明(解释前文为什么capacity是16而不是别的)

vs下string的结构
string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字符串的存储空间:
当字符串长度小于16时,使用内部固定的字符数组来存放
当字符串长度大于等于16时,从堆上开辟空间

class string//猜测是这样子的
{
private:
	char* _ptr;//如果小于16字节,那么存在在_buf中,但如果大于就会用_ptr指堆开辟的空间
	char _buf[16];
	size_t _size;
	size_t _capacity;
};

在这里插入图片描述
一个指针+16字节空间+1个size_t字段保存字符串长度+1个size_t字段保存从堆上开辟空间总的容量
4+16+4+4=28
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青青丘比特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值