C++深入学习string类成员函数(2):容器管理

引言

C++ 标准库中的容器(如 std::string、std::vector、std::list 等)都提供了一系列容器管理成员函数,用于处理容器的大小、容量、清空等操作。容器管理成员函数可以分为几类,主要包括容量查询、修改容器大小、清空容器等操作

以下是常见的容器管理成员函数(适用于大多数标准库容器,如 std::string, std::vector 等),我们在此只介绍这些成员函数在string类中的操作:

1.容量查询函数

这些函数用于查询容器的大小和容量信息。

1.1 size()与length()

size()和 length()作用相同,都用于返回字符串的长度,返回类型都是size_t。

(1)函数原型

size_t size() const noexcept;
size_t length() const noexcept;

- const:关键字const表示该函数是常量成员函数,即它不会修改当前对象的状态。

- noexcept:noexcept表示该函数在执行时不会抛出任何异常,即无论什么情况下,调用size()都不会引发异常。 

(2)示例代码

#include <iostream>
using namespace std;
 
int main()
{
	string s = "Hello";
	cout << s.size() << endl;//5
	cout << s.length() << endl;//5
	return 0;
} 

两者没有功能上的区别,提供两个概念主要是为了与开发者的习惯保持一致,size_t()更符合容器类的术语,length()更符合处理字符串的自然语言概念。

1.2 capacity()

    std::string 类中的 capacity() 函数用于返回当前字符串对象分配的内存容量大小(不包括末尾的空终止符 '\0'),这个容量表示在不重新分配内存的情况下,字符串最多可以容纳的字符数量。

- 与 size() 不同,size() 返回的是当前字符串中实际存储的字符数,而 capacity() 则表示分配的空间总量(不包括末尾的空终止符 `'\0'`),通常比 size() 大,特别是在进行字符串扩展时。

(1)函数原型

size_t capacity() const noexcept;

(2)示例代码 

#include <iostream>
using namespace std;


int main()
{
	string s1 = "Hello, Welcome";

	cout << s1.size() << endl;//7
	cout << s1.capacity() << endl;//15

	s1 += " to henu";

	cout << s1.size() << endl;//22
	cout << s1.capacity() << endl;//31

	return 0;
}

- 当字符串需要扩展并超出当前的容量时,系统会自动重新分配更多的内存空间,以容纳更多字符。  

(2)总结
- capacity() 返回当前字符串分配的总内存量,可以在不重新分配内存的情况下容纳的最大字符数。
- capacity() 通常大于 size(),以避免频繁的内存分配操作,提高性能。
- 通过 reserve() 预分配内存,或者通过 shrink_to_fit() 释放未使用的空间,可以调整字符串的容量管理行为。

1.3 其它成员函数

1.3.1 max_size()

max_size():返回容器可以存储的最大元素数量,这并不是你实际分配到的内存容量,而是字符串理论上能达到的最大大小,由系统和标准库的实现决定。

size_t max_size() const noexcept;
#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello";
	cout << s1.max_size() << endl;//9223372036854775807
	return 0;
}

1.3.2 empty()

empty():检查容器是否为空,返回布尔值 true 表示容器为空,false 表示不为空。

bool empty() const noexcept;
#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello";
	string s2;

	cout << s1.empty() << endl;// 输出 0(false),因为 str 是不是空的
	cout << s2.empty() << endl;// 输出 1(true),因为 str 是空的

	return 0;
}

 

2. 修改容器大小的函数

这些函数用于修改容器的大小或容量。

2.1 reverse()

    std::strin 类的 reserve() 函数用于预分配内存,调整字符串的 capacity,以避免在字符串扩展时频繁重新分配内存。这是一种优化技术,可以提高性能,尤其是在已知字符串将增长到较大大小的情况下

(1)函数原型

void reserve (size_t new_cap);

- new_cap:这是你希望字符串预分配的最小容量。如果 new_cap 小于当前 capacity(),调用 reserve() 不会减少现有的容量。如果 new_cap 大于当前 capacity(),则分配足够的内存以满足 new_cap 的要求
  
- 默认行为:如果没有传递参数,默认行为是将字符串的容量保持为当前值,不会额外分配空间
。 

(2)关键点

- reserve() 只调整 capacity(),不影响当前字符串的 size() 和内容。
- 如果你提前知道字符串可能会变得很大,使用 reserve() 可以避免在多次添加字符时频繁地重新分配内存。

(3)示例代码

#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello";

	cout << s1.size() << endl;//5
	cout << s1.capacity() << endl;//15

	s1.reserve(50);

	s1 += ", this is a long sentence that we are appending!";

	cout << s1.size() << endl;//53
	cout << s1.capacity() << endl;//63

	return 0;
}

调用 reserve(50) 后得到 63 个字符的容量是标准库的一种优化策略。C++ 标准库为了减少频繁的内存分配开销,通常会分配比你实际请求更多的内存使用指数增长或倍数增长的方式来优化性能。因此,分配的容量可能大于你请求的大小,这是正常且预期的行为。

(4)总结
- reserve() 提前分配内存但不改变字符串的大小。
- 它优化了频繁增长的场景,减少了不必要的内存重新分配。
- 使用 reserve() 可以提高代码在处理大字符串时的性能。

2.2 其它成员函数

2.2.1 resize()

resize(size_type n)用来调整容器大小。若 n 大于当前大小,则增加新元素(对于 std::string,新增的字符是 \0 或指定的字符);若 n 小于当前大小,则移除多余的元素。

void resize (size_t n);
void resize (size_t n, char c);

它有两个重载版本:

1. resize(size_t n):将字符串的大小调整为 n,如果 n 小于当前大小,则截断字符串;如果 n 大于当前大小,则在字符串末尾添加空字符 `\0`。
   
2. resize(size_t n, char c):将字符串的大小调整为 n,如果 n 小于当前大小,则截断字符串;如果 n 大于当前大小,则在字符串末尾添加字符 c 来填充。

#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello, henu";
	
	s1.resize(5);//调整字符串大小为5,截断字符串
	cout << s1 << endl;

	s1.resize(20, 'x');//调整字符串大小为20,用'x'填充字符串
	cout << s1 << endl;

	return 0;
}

- resize() 可以用来增大或缩小字符串的大小。
- 增大时可以用指定字符填充,不指定时使用空字符 `\0`。
- 缩小时会截断字符串。

2.2.2 shrink_to_fit()

shrink_to_fit() 用来缩小字符串的容量使其与当前字符串的大小一致,释放多余的内存。

- 不过shrink_to_fit() 是非强制性的,标准库实现可以选择是否实际执行这个操作。通常取决于库的具体实现。尽管你调用了它,容量不一定会完全匹配大小,但库会尽量缩小容量

void shrink_to_fit();
#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello";

	cout << s1.size() << endl;//5
	cout << s1.capacity() << endl;//15

	s1.shrink_to_fit();

	cout << s1.size() << endl;//5
	cout << s1.capacity() << endl;//5

	return 0;
}

 

3. 清空和删除元素的函数

这些函数用于清空容器或删除元素。

3.1 clear()

clear()用来清空容器中的所有元素,使其 size 变为 0,它不会改变字符串的容量。

(1) 函数原型:

void clear() noexcept;

- 清空字符串内容,将字符串长度变为 0。
- 该函数是 noexcept 的,这意味着它保证不会抛出异常。

(2)示例代码:

#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello, henu";
    cout << s1 << endl;//Hello, henu
    cout << s1.size() << endl;//11
    cout << s1.capacity() << endl;//15

	s1.clear();//清空字符串
	cout << s1 << endl;//
	cout << s1.size() << endl;//0
	cout << s1.capacity() << endl;//15

	return 0;
}

(3) 总结:

- clear() 清空字符串的内容,长度变为 0。
- clear() 不会影响字符串的容量(即预分配的内存),如果你想释放多余的内存,可以结合使用 shrink_to_fit()。
- clear() 是一个非常高效的操作,适用于需要多次复用同一字符串的场景。

3.2 Erase

用于删除字符串中的一个或多个字符。它有几种不同的重载方式,允许根据不同的需求删除字符。 

(1)函数原型:

sequence (1)	string& erase (size_t pos = 0, size_t len = npos);
character (2)   iterator erase (const_iterator p);
range (3)       iterator erase (const_iterator first, const_iterator last);

1. erase(size_t pos = 0, size_t len = npos)
   - 从字符串中删除从位置 pos 开始的 len 个字符。
   - npos 是一个特殊值,表示“直到字符串的末尾”。
   - 返回值是 this,即调用此函数的字符串自身。
  
2. iterator erase(const_iterator position)
   - 删除迭代器 position 指向的字符。
   - 返回值是一个指向删除元素之后元素的迭代器。

3. iterator erase(const_iterator first, const_iterator last)
   - 删除从 first 到 last 范围内的字符(last 不包括在内)。
   - 返回值是一个指向删除范围之后第一个字符的迭代器。

(2)示例代码 

#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello, henu";

	s1.erase(5, 2);//删除第五个字符后的两个字符
	cout << s1 << endl;//Hellohenu
	s1.erase(5, 4);
	cout << s1 << endl;//Hello

	s1.erase(s1.begin());//删除H
	cout << s1 << endl;//ello
	s1.erase(s1.begin() + 3);//删除o
	cout << s1 << endl;//ell

	string s2 = "Hello, henu";
	s2.erase(s2.begin() + 5, s2.begin() + 10);//删除[',','u')之间的字符
	cout << s2 << endl;//Hello

	s1.erase();//删除整个字符串
	s2.erase();
	cout << s1 << endl;
	cout << s2 << endl;

	return 0;
}

(3)总结:

- erase() 可以删除从指定位置开始的一个或多个字符。
- 可以通过迭代器删除指定的字符或字符范围。
- erase() 是一个高效的操作,适用于修改字符串内容。

4. 交换函数

     swap()能够交换两个容器的内容,它通过交换字符串的内部数据指针来实现,不涉及字符的逐一拷贝,因此操作非常高效,在效率上比逐个交换元素更好,时间复杂度为 O(1)。

(1)函数原型:

void swap (string& str);

- 交换当前字符串和参数 str 的内容。
- 由于是 noexcept 的函数,它保证不会抛出异常。

(2)示例代码:

#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello";
	string s2 = "henu";

	s1.swap(s2);

	cout << s1 << endl;//henu
	cout << s2 << endl;//Hello

	return 0;
}

swap() 函数的效率很高,因为它只交换字符串对象的内部指针,而不涉及字符的复制操作。

(3)全局 swap() 函数:
除了 std::string 的成员函数 swap() 之外,C++ 还提供了一个全局的 std::swap() 函数,可以用来交换任意两个类型相同的对象,包括 std::string:

#include <iostream>
using namespace std;

int main()
{
	string s1 = "Hello";
	string s2 = "henu";

	//s1.swap(s2);
	swap(s1, s2);

	cout << s1 << endl;//henu
	cout << s2 << endl;//Hello

	return 0;
}

(4)std::swap 和 string::swap 的区别:
- std::swap 是一个全局函数,可以交换任意类型的两个对象,不局限于 std::string。
- string::swap 是 std::string 类的成员函数,专门用于交换两个字符串对象。

总结:

容器管理成员函数主要用于处理容器的大小和容量,以下是它们的分类:
1. 容量查询函数:size()、length(),max_size(),capacity(),empty()。
2. 修改容器大小的函数:resize(),reserve(),shrink_to_fit()。
3. 清空和删除元素的函数:clear(),erase()。
4. 交换函数:swap()。

这些函数在容器的动态管理中非常常用,能够有效地控制容器的内存和元素管理。

 更多string类的成员函数:string - C++ Reference (cplusplus.com) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/883191.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安卓13设置动态显示隐藏第一页的某一项 动态显示隐藏无障碍 android13设置动态显示隐藏第一页的某一项

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改4.1修改方法14.2修改方法25.编译6.彩蛋1.前言 有时候,我们的设置里面显示的信息,需要根据不同的情况显示不同的信息,例如,动态的显示或者隐藏 “无障碍” 这一项。 2.问题分析 像这个问题…

基于 K8S kubernetes 搭建 安装 EFK日志收集平台

目录 1、在k8s中安装EFK组件 1.1 安装elasticsearch组件 1.2 安装kibana组件 1.3 安装fluentd组件 文档中的YAML文件配置直接复制粘贴可能存在格式错误&#xff0c;故实验中所需要的YAML文件以及本地包均打包至网盘 链接&#xff1a;https://pan.baidu.com/s/15Ryaoa0_…

Leetcode面试经典150题-39.组合总数进阶:40.组合总和II

本题是扩展题&#xff0c;真实考过&#xff0c;看这个题之前先看一下39题 Leetcode面试经典150题-39.组合总数-CSDN博客 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数…

Java查找算法——(四)分块查找(完整详解,附有代码+案例)

文章目录 分块查找1.1普通分块查找 分块查找 1.1普通分块查找 分块原则&#xff1a; 块内无序&#xff0c;块间有序:前一块中的最大数据&#xff0c;小于后一块中所有的数据&#xff0c;块与块之间不能有数据重复的交集。块的数量一般等于数字个数开根号 核心思路&#xff…

CentOS Linux教程(6)--CentOS目录

文章目录 1. 根目录2. cd目录切换命令3. CentOS目录介绍4. pwd命令介绍5. ls命令介绍5.1 ls5.2 ls -a5.3 ls -l 1. 根目录 Windows电脑的根目录是计算机(我的电脑)&#xff0c;然后C盘、D盘。 Linux系统的根目录是/&#xff0c;我们可以使用cd /进入根目录&#xff0c;然后使…

VUE条件树查询

看如下图所示的功能&#xff0c;是不是可高级了&#xff1f;什么&#xff0c;你没看懂&#xff1f;拜托双击放大看&#xff01; 是的&#xff0c;我最近消失了一段时间就是在研究这个玩意的实现&#xff0c;通过不懈努力与钻研并参考其他人员实现并加以改造&#xff0c;很好&am…

南开大学联合同济大学发布最新SOTA Occ OPUS:使用稀疏集进行占据预测,最快实现8帧22FPS

Abstract 占据预测任务旨在预测体素化的 3D 环境中的占据状态&#xff0c;在自动驾驶社区中迅速获得了关注。主流的占据预测工作首先将 3D 环境离散化为体素网格&#xff0c;然后在这些密集网格上执行分类。然而&#xff0c;对样本数据的检查显示&#xff0c;大多数体素是未占…

Windows内核编程基础(3)

内存分配 在应用层编程时&#xff0c;系统提供了GlobalAlloc/HeapAlloc/LocalAlloc等函数。C/C库提供了malloc函数&#xff0c;以及new操作符在堆上分配内存。 在我前面一个关于Windows页交换文件的博客中&#xff0c;介绍了虚拟内存&#xff0c; 虚拟内存是计算机系统内存管…

Unity开发绘画板——03.简单的实现绘制功能

从本篇文章开始&#xff0c;将带着大家一起写代码&#xff0c;我不会直接贴出成品代码&#xff0c;而是会把写代码的历程以及遇到的问题、如何解决这些问题都记录在文章里面&#xff0c;当然&#xff0c;同一个问题的解决方案可能会有很多&#xff0c;甚至有更好更高效的方式是…

Go容器化微服务系统实战

1-1 本课的go微服务有什么不同&#xff1f; 聚焦于容器化可观测的购物微服务系统实战&#xff0c;通过介绍Go语言的应用趋势、容器化优势及微服务适用性&#xff0c;旨在解决学习微服务过程中遇到的难点。课程内容涵盖微服务整体架构、技术工具框架及容器平台等关键技术&#…

Java之路--瓦解逻辑控制与方法使用已是瓮中捉鳖

嗨嗨大家&#xff01;今天我们来学习逻辑运算和方法的使用~ 目录 一 逻辑控制 1 分支结构 1.1 if语句 1.2 switch 语句 2 循环结构 2.1 while 循环 2.2 for 循环 2.3 do while 循环 2.4 break 2.5 continue 3. 输出输入 二、方法的使用 1 方法定义语法 2 实参和…

苹果macOS 15.0 Sequoia正式版发布:iPhone应用镜像玩、手机消息电脑知

9月17日苹果向 Mac 电脑用户推送了 macOS 15 更新&#xff08;内部版本号&#xff1a;24A335&#xff09;&#xff0c;除了引入数个 iOS 18 的新功能外&#xff0c;macOS 15 Sequoia 还带来了全新的 Continuity 功能 ——iPhone 镜像。 iPhone 镜像功能可以让用户直接在 Mac 上…

[Linux] Linux操作系统 进程的状态

标题&#xff1a;[Linux] Linux操作系统 进程的状态 个人主页&#xff1a;水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、前置概念的理解 1.并行和并发 2.时间片 3.进程间具有独立性 4.等待的本质 正文开始&#xff1a; 在校的时候&#xff0c;你一定学过《…

图解Transformer就这30页PPT,你们真不看啊

图解Transformer就这30页PPT&#xff0c;你们真不看啊 主要介绍了Seq2Seq模型&#xff0c;慢慢引出了transformer的整体模型架构&#xff0c;比较具体的介绍了编码器部分的数据处理过程&#xff0c;包括了位置编码、多头注意力机制、残差连接、Layer Norm以及前馈网络等基本结…

支付宝沙箱环境 支付

一 什么是沙箱&#xff1a; 沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境 支付宝正式和沙箱环境的区别 &#xff1a; AI&#xff1a; 从沙箱到正式环境&#xff1a; 当应用程序开发完成后&#xff0c;需要将应用程序从沙箱环境迁移到正式环境。 这通常涉及…

如何查看线程

1、首先找到我们的电脑安装jdk的位置&#xff0c;这里给大家展示一下博主本人的电脑jdk路径下的jconsole位置。 2、 ok&#xff0c;那么找到这个jconsole程序我们直接双击打开就可以查看我们电脑的本地进程&#xff1a; jconsole 这里能够罗列出你系统上的 java 进程&#xff0…

古代经典名方目录数据库-支持经典名方检索!

"古代经典名方目录"是指一系列历史上流传下来的&#xff0c;被认为具有一定疗效的中药方剂的汇总。这些方剂多来源于历代医学典籍&#xff0c;经过长期临床实践的检验&#xff0c;部分已被收录于官方的目录之中&#xff0c;以便于现代医疗实践中的参考和应用。 目前…

手机在网状态查询接口如何用C#进行调用?

一、什么是手机在网状态查询接口&#xff1f; 手机在网状态查询接口是利用实时数据来对手机号码在运营商网络中的状态进行查询的工具&#xff0c;包括正常使用状态、停机状态、不在网状态、预销户状态等。 二、手机在网状态查询适用哪些场景&#xff1f; 例如&#xff1a;商…

设计模式-结构型-11-代理模式

文章目录 1. 基本介绍2. 静态代理2.1 基本介绍UML 类图 2.2 应用实例定义接口目标对象代理对象调用代理 2.3 静态代理优缺点 3. 动态代理3.1 基本介绍3.2 JDK 中生成代理对象的 API参数说明UML类图 3.3 应用实例定义接口目标对象代理工厂调用代理 4. Cglib 代理4.1 基本介绍4.2…

求一个数的因子数(c语言)

1.计算并输出给定整数n的所有因子&#xff08;不包括1与n自身&#xff09;之和。规定n的值不大于1000。&#xff08;因子是能整除n的数 即n%i0&#xff09; // 例如&#xff0c;在主函数中从键盘给n输入的值为856&#xff0c;则输出为: sum763。 2.第一步我们先输入n的数&…