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


相关推荐
老当益壮梁奶奶4 小时前
Linux软件编程学习笔记(七):线程分离与线程间通信详解
linux·c语言·c++·笔记·学习
水饺编程8 小时前
第5章,[Win32 章节] :绘图模式
c语言·c++·windows·visual studio
INGNIGHT9 小时前
1908 · 布尔表达式求值(stack单调栈&dfs)
开发语言·c++·算法
小小杨树9 小时前
【C++】学习:双缓冲视频流水线深解析
c++·性能优化·音视频开发
青少儿编程课堂10 小时前
图形化编程实战:智能交通灯调度台,一个作品讲透循环、条件与广播
c++·python·算法·bfs·信息学竞赛
赵民勇10 小时前
C++无锁编程详解
c++
醉颜凉11 小时前
C++ 中野指针与悬挂指针的区别:从成因到防范,彻底讲清两种危险指针
c++
Demon--hx11 小时前
设计不能被继承的类
开发语言·c++
兔兔兔兔111 小时前
记录C++ 13
开发语言·c++·算法
开心大爆炸12 小时前
ubuntu20.4 安装ros1 noetic版本流程
c++