C++ STL容器string(一):string的变量细节、默认函数的认识以及常用接口的使用


文章目录

  • 前言
  • 一、认识string
    • [1.1 string 是什么](#1.1 string 是什么)
    • [1.2 string相关资料](#1.2 string相关资料)
  • 二、编码对于string的作用
    • [2.1 编码是什么](#2.1 编码是什么)
    • [2.2 编码与string的联系](#2.2 编码与string的联系)
  • 三、默认构造函数
    • [3.1 构造函数](#3.1 构造函数)
    • [3.2 赋值运算符重载](#3.2 赋值运算符重载)
    • [3.3 析构函数](#3.3 析构函数)
  • 四、三种常用遍历
    • [4.1 operator[ ]](#4.1 operator[ ])
      • [4.1.1 size()](#4.1.1 size())
      • [4.1.2 operator[ ]的使用](#4.1.2 operator[ ]的使用)
    • [4.2 iterator迭代器](#4.2 iterator迭代器)
      • [4.2.1 迭代器是是什么](#4.2.1 迭代器是是什么)
      • [4.2.2 关于迭代器的用法](#4.2.2 关于迭代器的用法)
      • [4.2.3 迭代器遍历操作](#4.2.3 迭代器遍历操作)
    • [4.3 auto范围for](#4.3 auto范围for)
  • 五、容量相关接口
    • [5.1 查询容量](#5.1 查询容量)
    • [5.2 修改容量](#5.2 修改容量)
      • [5.2.1 string 的数据存储](#5.2.1 string 的数据存储)
      • [5.2.2 reserve()接口](#5.2.2 reserve()接口)
      • [5.2.3 resize()](#5.2.3 resize())
      • [5.2.3 clear()接口](#5.2.3 clear()接口)
      • [5.2.4 empty()接口](#5.2.4 empty()接口)
      • [5.2.5 shrink_to_fit()接口](#5.2.5 shrink_to_fit()接口)
  • 总结

前言

C++历久弥新的元素有什么?我可以大胆的说其中就有STL库的伟大功劳,那么STL库是什么、它又有什么呢?今天我们将学习STL库中的string,通过该容器看管中窥豹,见识STL的伟大。


一、认识string

1.1 string 是什么

C++ 的 string 类是C++ 标准库(STL)提供的一个专门用于处理字符串的封装类,定义在 头文件中,属于 std 命名空间 (一定要包头文件)。

它相当于一个工具箱,在你对字符类型的数据处理时可以随意使用里面的工具即"函数方法",省略了我们造工具的过程。

  • 核心组成:
    数据成员:存储字符的数组、当前字符串长度、已分配的内存容量等
    成员函数:操作字符串的方法(size()、find()、replace() 等)
    重载运算符:让 +、==、[] 等运算符能直接用于字符串操作(这是它最方便的特性之一)
  • 核心特性:
    初始化时,根据字符串长度分配内存
    拼接 / 扩容时,自动重新分配更大的内存,拷贝原有内容,释放旧内存
    销毁时,自动释放占用的内存(无需手动 free/delete)

接下来让我们从各个角度来认识吧

1.2 string相关资料

接下来**C++string文档**(点击跳转)文件很有用,下面的讲解也会根据这个cplusplus文档来讲解。


二、编码对于string的作用

2.1 编码是什么

&emsp ;编码 就是把一种信息,按照固定规则,转换成另一种统一格式的符号 / 数字 / 代码,方便存储、传输、识别、使用。如我们常用的ASCII码就是一种编码

c但可以发现这个编码只支持了英文与数字的转换,为了改变这种现象,又出现了许多编码,如:GBK(中文编码)、万国码(UTF-系列)等等,实现了数字与语言的对应。

2.2 编码与string的联系


三、默认构造函数

3.1 构造函数

编号 语法 说明 使用方法
1 string() 默认构造 无参构造,即创造空字符串
2 string (const string& str) 拷贝构造 用已有的string对象进行构造
3 string (const string& str, size_t pos, size_t len = npos) 字串构造 从已有string对象的pos下标取len长度构造**(超出长度则取到末尾),不传长度视为全部(默认npos为-1)**
4 string (const char* s) C语言字符串构造 "\n"为结尾 的字符数组
5 string (const char* s, size_t n) C语言字串构造 从字符数组的pos下表取len长度构造,与上同理
6 string (size_t n, char c) 字符构造 以某一字符c,连续n个构造
7 template string (InputIterator first, InputIterator last) 迭代器构造 指向char的指针构造(迭代器底层为指针)
8 string (initializer_list il) 初始化列表构造 用{ }里的字符构造
9 string (string&& str) noexcep 移动构造 转移已有资源构造新对象

标红的构造方法为常用方法,其他知道即可,并且编号8、9是C++11新出的两种方法,涉及到初始化列表和右值以及异常的使用(今后的章节将会讲解)。

3.2 赋值运算符重载

编号 语法 说明 使用方法
1 string& operator= (const string& str) 字符串赋值 用string对象赋值
2 string& operator= (const char* s) C语言字符串赋值 使用以 "\n "结尾的 C 字符串(如 "Hello")赋值。
3 string& operator= (char c) 字符赋值 以单个字符赋值
4 string& operator= (initializer_list il) 初始化列表赋值 初始化列表构造
5 string& operator= 移动赋值 将已有的资源转移

编号5为C++11新语法,现在不需要了解

3.3 析构函数

在对象的生命周期结束时自动调用,释放资源。


四、三种常用遍历

4.1 operator[ ]

operator[ ] 的实现还需要其他接口的帮助,让我们先来了解一下这些接口。

4.1.1 size()

调用size()接口就可以取出该字符串的长度了,当然文档里还有个length接口,其实与size用法一致,size是后来实现为和其他容器一致。

4.1.2 operator[ ]的使用

函数返回值为字符串对象pos下标的字符引用

cpp 复制代码
string s1("hello world")
for(int i = 0;i < s1.size();i++)
{
	cout >> s1[i] >> " ";
}

4.2 iterator迭代器

4.2.1 迭代器是是什么

迭代器是一种用于遍历容器(集合、序列)元素的对象,提供统一接口,能依次访问集合中的每一个元素,且不暴露容器内部结构。

STL里的每个容器都有它独有的迭代器,实现底层不尽相同,这里底层为指针,后面不同在做讲解,与其他类型定义变量的语法相同,都是类型+变量名。

4.2.2 关于迭代器的用法

函数名 属性 返回值 说明
begin() iterator 返回指向容器第一个元素的正向迭代器
end() iterator 返回指向容器最后一个元素后一个位置的正向迭代器
rbegin() 反向 reverse_iterator 返回指向容器最后一个元素的反向迭代器(从后往前)
rend() 反向 reverse_iterator 返回指向容器第一个元素前一位置的反向迭代器
cbegin() const只读 const_iterator 返回指向容器第一个元素的正向只读迭代器
cend() const只读 const_iterator 返回指向容器最后一个元素后一个位置的正向只读迭代器
crbegin() const只读 、反向 const_reverse_iterator 返回指向容器最后一个元素的反向只读迭代器
crend() const只读 、反向 const_reverse_iterator 返回指向容器第一个元素前一位置的反向只读迭代器

蓝色标出的是日常中常用的迭代器,需要着重记忆。

4.2.3 迭代器遍历操作

cpp 复制代码
string::iterator it = s1.begin();
for(;it != s1.end();it++)
{
	cout << *it << " ";
}

里面代码底层实现是依靠重载实现的,格式与我们之前的遍历几乎一致,今后这个方式将会一直陪伴我们的学习。

4.3 auto范围for

C++11引进的新语法,作用为自动推导类型。

自动推导变量类型,不用手动写 int、char、string 等类型

cpp 复制代码
//for(auto& e:arr)
for(auto e: arr)
{
	cout << e << " ";
}

在引用的情况下可以直接对e存储的数据直接进行修改,底层就是迭代器,具有自动迭代、自动判断的特点。(因此所有容器都支持范围for)

如图,在反汇编中可以发现调用了封装的begin与end

auto 不要随便作为函数的返回值与参数


五、容量相关接口

5.1 查询容量


编号 函数名 返回值 作用
1 length() size_type 返回字符串的有效长度(最后索引 - 0索引 + 1)
2 size() size_type 与length()相同,因为兼容性并为统一STL标准存在
3 max_size() size_type 返回字符串的最大长度(实际上与返回值的字节数有关)
4 capacity() size_type 查看字符串目前最大容量,判断是否扩容

容量的接口常用的只有size和capacity,其他的了解即可。

5.2 修改容量

想要修改容量就必须先知道string的存储方式,才能对其的容量做出修改操作。

5.2.1 string 的数据存储

了解其底层就离不开它的存储方式,下图就是监视窗口中其显示的变量部分,我们讲解其中部分变量 来了解底层的方法。

名称 类型 作用
_Buf char[16] 字符串的临时存储位置,当size小于16时存在buff中,大于则废弃
_Ptr char* 当字符串size大于16时,字符串存储位置
_Mysize size_t 字符串的真实长度
_Myres size_t 字符串现在最大的容量(当size等于其时,扩容)

当然在操作系统不同时,底层的扩容逻辑不同,如:VS是1.5倍,Linux的g++是2倍。

5.2.2 reserve()接口

  • 作用:
  1. 直接修改_Myres变量,提前开好设置好的空间,实际空间会大于等于输入空间(vs有整数对齐功能),而g++不会
  2. 当目前容量大于设定容量,编译器会发起不具有强制性的缩容请求,不同编译器处理情况不同,vs不会缩,容而g++会缩容。
情况 变化
n < size vs和g++ 都不缩容
size < n < capacity vs不缩容,g++缩容
n > capacity 两者都扩容

5.2.3 resize()

  • 作用:
  1. 将字符长度设置为输入的变量n个长度。
  2. 如果n小于当前字符串的size时,就会将size设置为n,并且移除n长度后的内容
  3. 如果n大于size且小于capacity时,就会将size设置为n,并且在原来的末尾插入空字符(\0)使达到n的长度
  4. 如果n大于capacity时,会先扩容再续写。

5.2.3 clear()接口

删除string的存储的内容,并把size设置为0,一般不会影响capacity。

5.2.4 empty()接口


判断是否为空接口

判断string是否为空,为空返回true。

5.2.5 shrink_to_fit()接口

缩减capacity使其等于size (不计算\n),同reverse将n 小于 capacity时相似都是非强制性的请求,可能会使得capacity大于size


总结

这就是本节的全部内容了,string是第一个接触到的STL容器,所以讲的比较详细,在后面容器的讲解则会省略所以的共同内容,感谢您的阅读,在本篇我们学会了string的默认函数、遍历方法、迭代器、容量接口,接下来我们将学会更多内容。

相关推荐
代码中介商1 小时前
C++ STL 标准模板库完全指南:从容器到迭代器
开发语言·c++·stl
winner88811 小时前
C++ 构造函数、析构函数、虚函数、虚析构
开发语言·c++
想唱rap1 小时前
应用层协议与序列化
linux·运维·服务器·网络·数据结构·c++·算法
北山有鸟1 小时前
IS_ERR 判断出错后,再用 PTR_ERR 把它强制转换回 int 型的错误码作为函数的返回值。
java·开发语言
许长安1 小时前
protobuf 使用详解
c++·经验分享·笔记·中间件
格林威1 小时前
工业视觉检测:提供可视化UI调试工具的实现方式是什么?
开发语言·人工智能·数码相机·ui·计算机视觉·视觉检测·工业相机
Soley1 小时前
用 Boost.Log 封装一个更顺手的 C++17 日志库:GoodLog
c++
phltxy1 小时前
深度解析:Spring Cloud Gateway 从入门到实战
java·开发语言
HAPPY酷2 小时前
从Public到Private:UE5 C++类创建路径差异全解析
java·c++·ue5