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()


相关推荐
C+++Python18 分钟前
C++ 泛型编程 极简示例代码
开发语言·c++
宵时待雨29 分钟前
回溯算法专题2:二叉树中的深搜
开发语言·数据结构·c++·笔记·算法·深度优先
计算机安禾1 小时前
【c++面向对象编程】第21篇:运算符重载基础:语法、规则与不可重载的运算符
java·前端·c++
开发者联盟league1 小时前
在cursor中配置c/c++开发环境
c语言·开发语言·c++
澈2071 小时前
平衡二叉树:AVL与红黑树终极对比
数据结构·c++·红黑树
ComputerInBook2 小时前
C++ 中的 lambda 表达式
开发语言·c++·lambda表达式·匿名函数
刃神太酷啦2 小时前
《网络基础全链路深度解析:从Socket编程到HTTPS与TCP/UDP内核机制》----《Hello Linux!》(25)
linux·运维·c语言·网络·c++·tcp/ip·https
paeamecium3 小时前
【PAT甲级真题】- Shuffling Machine (20)
c++·算法·pat考试·pat
不想写代码的星星3 小时前
C++协程从入门到放弃?不,是从入门到手搓调度器
开发语言·c++
redaijufeng3 小时前
C++构造函数详解:从基础原理到实际应用
java·jvm·c++