string(2)

string

1、auto

C++11规定了一个关键字:auto,auto通过初始化表达式的值类型,自动推导对象类型。

cpp 复制代码
auto i = 10;//一般推导出int
auto j = 1.2;//一般推导出double

auto可以推导出指针类型。

上面的写法可以推导出int*类型,也可以推导出其它的类型。

然而,下面这样写,只能推导出int*类型:

auto也可以推导出引用类型,但是auto必须加上&,否则不能识别出引用类型:

可以看到,前三个地址相同,说明auto&推导出了引用类型;但是第四个地址不同,说明auto推导不出引用类型。

那么auto有什么用呢?

比如我们有一个string对象,然后又使用了迭代器:

我们写string迭代器类型,就需要写这么一个长长的东西。

这时我们用一个auto,去自动推导类型:

这就达到了简化代码的效果。

但是,频繁使用auto,会降低代码的可读性。我们要尽量避免通篇使用auto的情况发生。

2、范围for

C++11也规定了一个很新的语法,叫范围for

范围for看上去自动实现了三步:

  • 自动取容器数据赋值
  • 自动迭代
  • 自动判断是否结束

上面的代码只是打印了数据。如果我们要想改变数据,就需要使用引用:

上面的代码都是对stirng(和容器)操作。其实范围for也可以对数组操作:

范围for底层实现上,可能替换成了迭代器。

3、零碎接口(成员函数)

max_size()

max_size()返回的是对象可以达到的最大的存储元素的个数。

但是这个接口用得不多。

size()

size()返回的是对象实际存储有效元素的个数。

capacity()

capacity()返回的是对象当前最大空间(最多可以存多少个元素)。

clear()

顾名思义:清理内容(但不清理空间资源)。

void_pushback()

这是尾插接口。

4、string容量和实际大小的改变

我们创建一个s1,往里面放100个字符,然后观察一下s1容量的变化:


当前s1实际空间是16个字节,只不过最后一个字节存了一个\0,同时不显示出来,也不计入s1的实际内容。

我们可以看到,vs 2022的Debug版本下,s1扩容的规律是:

  • 第一次扩容两倍
  • 以后扩容1.5倍

STL的设计,其实是一种规范。STL规定的是要实现哪些容器、算法、接口...具体如何实现,取决于不同的平台。

Linux下,gcc的4.8.5版本,是二倍扩容:

C++提供了一个手动扩容的接口:reserve()

4.1、reserve()

划红线处,是两个细节:

  • 如果输入的n大于原来的容量,那么reserve()可能会申请到相应的空间,甚至更大.
  • 对于使用n缩小s1容量的请求是非绑定的,也就是不一定会缩小空间。

比如我们将原来的s1扩容到20个元素:

可以发现,扩的更多了。

我们又另外将s1缩容到五个元素:

可以发现,并没有缩容。这也与reserve()不会改变s1的内容相对应。

但是,我们还是建议,不要用reserve()缩容。(系统不会部分释放,必须异地缩容,造成性能浪费)

reserve()的核心作用,就是:假设有200个字符需要插入,那么就可以事先用reserve()开辟好空间,以减少自动扩容(多次异地扩容)带来的代价。

真要扩容,我们可以使用:shrink_to_fit()。

4.2、shrink_to_fit()

我们在vs2022和Linux(4.8.5)下看看shrink_to_fit()的作用:


我们可以看到,vs2022下没有缩容,Linux下进行了缩容。也就是说,缩容与否,取决于编译器。

一般情况下,我们还是不建议缩容,因为编译器不会释放部分空间,而是异地扩容,用时间换空间。

4.3、resize()

接口resize(),实现了对对象实际大小的改变。

我们前面的扩缩容,不会改变size()。但是resize()不一样。

如果输入参数n小于对象的size(),那么对象的前n个元素会被保留,其余的会被删除:

如果n大于,就会扩容;如果又指定字符,那么剩余空间就会用这个字符填充:

5、string的修改

5.1、append()

append()是一个追加内容的接口。

值得注意的是,如果追加的内容超过了当前对象的剩余容量,对象会扩容:

append()还可以使用迭代器传参,追加的内容是对应对象的迭代器区间的内容:

5.2、operator+=

operator+=也可以追加内容,并且它被重载成了成员函数:

operator+没有重载成成员函数。

原因是:operator+没有重载成成员函数,就可以实现以下操作。

要是operator+重载成了成员函数,那么第一个参数默认是对象(const指针),那么就不会有写法2,就不灵活了。


operator>等比较接口也没有重载成成员函数:

5.3、assign()

assign()其实与append()非常相似:

事实上,我们更经常用operator+=,因为方便理解。

5.4、指定位置的插入、删除

插入接口:

string中没有实现头插接口,所以我们只能用insert()。

但是使用insert()进行头插操作,效率是不太高的。(我们在之前的数据结构学习中就知道,包含数组的数据结构,头插是要挪动其他数据的)

删除接口:

5.5、replace()


相关推荐
牢姐与蒯21 小时前
c++数据结构之二叉搜索树
数据结构·c++·搜索
Morwit21 小时前
【力扣hot100】 416. 分割等和子集
数据结构·c++·算法·leetcode·职场和发展
qeen8721 小时前
【算法笔记】二分查找与二分答案
c语言·c++·笔记·学习·算法·二分
Sylvia-girl1 天前
类与对象(下)
c++·友元函数·类与对象
Hello eveybody1 天前
介绍最大公因数和最小公约数(C++)
java·开发语言·c++
宵时待雨1 天前
优选算法专题3:二分查找
数据结构·c++·算法·leetcode·职场和发展
Byte不洛1 天前
理解C++异常机制:栈展开、异常传播与异常安全
c++·异常处理·后端开发·编程基础·try catch
我头发多我先学1 天前
C++ AVL 树:平衡原理到完整实现(自平衡二叉搜索树)
开发语言·数据结构·c++·算法
啊我不会诶1 天前
2025浙江省赛补题
c++·算法
郝学胜-神的一滴1 天前
epoll 边缘触发 vs 水平触发:从管道到套接字的深度实战
linux·服务器·开发语言·c++·网络协议·unix