【C++】string 类深度解析:探秘字符串操作的核心

 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 

 


目录

💯前言

💯为什么要学习 string 类

(一)简化操作

(二)确保安全

(三)满足需求

💯标准库中的 string 类

(一)定义与头文件

💯string 类的内部结构

(一)数据成员

(二)内存管理

💯string 类的构造函数

(一)默认构造函数

(二)带参数的构造函数

💯string 类的成员函数

(一)获取字符串信息的函数

1.length () 和 size () 函数

2.capacity () 函数

(二)字符串修改函数

1.append () 函数

2.insert () 函数

3.erase () 函数

(三)字符串比较函数

1.compare () 函数

(四)字符串查找函数

1.find () 函数

2.rfind () 函数

💯string 类的浅拷贝与深拷贝

(一)浅拷贝

(二)深拷贝

💯string 类的操作符重载

(一)赋值操作符(=)

(二)加法操作符(+)

(三)下标操作符([])

💯总结


💯前言

🎦在 C++ 编程中,字符串处理至关重要。你是否曾困惑于字符数组操作的复杂性和潜在风险?

C++ 的string类提供了便捷、安全的解决方案。深入了解它,对提升编程能力和代码质量意义重大。😝


💯为什么要学习 string 类

(一)简化操作

🙋使用字符数组处理字符串繁琐且易错,string类如何简化这些操作呢?

它提供了直观的接口自动管理内存等,减少了编程复杂性。

(二)确保安全

🙋字符串操作易出现越界访问等安全问题,string类是怎样避免这些问题,保障代码安全的呢?

它有完善的内存管理边界检查机制

(三)满足需求

🙋现代编程中字符串处理需求多样,string类具备哪些特性来满足不同领域需求呢?

它提供了丰富的功能,适用于文本处理、网络通信等多个方面。

 


💯标准库中的 string 类

(一)定义与头文件

string是 C++ 标准库中用于表示和操作字符串的类,定义在<string>头文件中。包含该头文件后,即可使用string类及其相关功能。

使用string类时,必须包含#include头文件以及using namespace std;

🙋它与 C 风格字符串有何联系呢?

它可从 C 风格字符串初始化,且通过c_str()函数与 C 风格字符串交互。

 


💯string 类的内部结构

(一)数据成员

string类内部包含指向字符数组的指针用于存储字符串内容,还有记录长度、容量等信息的成员变量。👀这些是如何协同工作来管理字符串的呢?

(二)内存管理

string类自动管理内存,当字符串长度变化时自动重新分配👀它是如何高效实现内存管理,避免浪费和频繁分配的呢?

👇现在我们就来解释这一系列问题~


💯string 类的构造函数

(一)默认构造函数

string类的默认构造函数创建空字符串。例如:

#include <iostream>
#include <string>using namespace std;int main() {string str;cout << "默认构造函数创建的字符串长度为: " << str.length() << endl;return 0;
}

(二)带参数的构造函数

  • 可使用const char*参数初始化string对象它是如何转换的呢?(下一篇文章我会提到)
    👇代码解释:
#include <iostream>
#include <string>using namespace std;int main() {const char* cstr = "Hello, World!";string str(cstr);cout << "使用字符数组初始化的字符串为: " << str << endl;return 0;
}

  • 也可用size_tchar参数初始化它如何确定初始容量呢?(下一篇文章我会提到)
    👇代码解释:
#include <iostream>
#include <string>using namespace std;int main() {string str(5, 'a');cout << "使用指定数量和字符初始化的字符串为: " << str << endl;return 0;
}


💯string 类的成员函数

函数名称功能说明
size(重点)⭐返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty(重点)⭐检测字符串释放为空串,是返回true,否则返回false
clear(重点)⭐清空有效字符
reserve(重点)⭐为字符串预留空间**
resize(重点)⭐将有效字符的个数该成n个,多出的空间用字符c填充

 

(一)获取字符串信息的函数

1.length () 和 size () 函数
  • 功能相同,返回字符串长度。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str = "Hello";cout << "字符串的长度为: " << str.length() << " 或 " << str.size() << endl;return 0;
    }

     

2.capacity () 函数

 

  • 返回当前分配的内存容量。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str = "Hello";cout << "字符串的容量为: " << str.capacity() << endl;return 0;
    }

(二)字符串修改函数

1.append () 函数
  • 在末尾添加字符串或字符数组。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str = "Hello";str.append(", World!");cout << "添加后的字符串为: " << str << endl;return 0;
    }

2.insert () 函数
  • 在指定位置插入字符串或字符数组。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str = "Hello World!";str.insert(5, ", ");cout << "添加后的字符串为: " << str << endl;return 0;
    }

3.erase () 函数
  • 删除指定部分。例如:
#include <iostream>
#include <string>using namespace std;int main() {string str = "Hello, World!";str.erase(7, 6);cout << "删除后的字符串为: " << str << endl;return 0;
}

(三)字符串比较函数

1.compare () 函数
  • 比较两个字符串大小关系。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str1 = "Hello";string str2 = "World";int result = str1.compare(str2);if (result == 0) {cout << "两个字符串相等" << endl;} else if (result < 0) {cout << "str1 小于 str2" << endl;} else {cout << "str1 大于 str2" << endl;}return 0;
    }

(四)字符串查找函数

1.find () 函数
  • 查找指定子字符串或字符首次出现位置。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str = "Hello, World!";size_t position = str.find("World");if (position!= string::npos) {cout << "找到子字符串的位置为: " << position << endl;} else {cout << "未找到子字符串" << endl;}return 0;
    }

2.rfind () 函数
  • 查找指定子字符串或字符最后一次出现位置。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str = "Hello, World!";size_t position = str.rfind("o");if (position!= string::npos) {cout << "找到子字符串的位置为: " << position << endl;} else {cout << "未找到子字符串" << endl;}return 0;
    }


💯string 类的浅拷贝与深拷贝

(一)浅拷贝

👻浅拷贝只是简单地复制对象的数据成员的值。

如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。 

😓就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一不想分享就你争我夺,玩具损坏。

 

👇代码解释:

#include <iostream>
#include <string>using namespace std;int main() {string str1 = "Hello";string str2 = str1; // 浅拷贝cout << "str1 的地址: " << &str1 << ", str2 的地址: " << &str2 << endl;cout << "str1 的指针成员地址: " << (void*)str1.data() << ", str2 的指针成员地址: " << (void*)str2.data() << endl;return 0;
}

 str1str2的指针成员指向相同的内存地址。这可能会导致问题,当其中一个对象对字符串进行修改时,另一个对象也会受到影响。

 

(二)深拷贝

为了避免浅拷贝带来的问题,string类通常会实现深拷贝。深拷贝会重新分配内存,并将原对象的数据完整地复制到新分配的内存中。

每个对象都有一份独立的资源,不要和其他对象共享。父母给每个孩子都买一份玩具,各自玩各自的就不会有问题了。

 👇代码解释:

#include <iostream>
#include <string>using namespace std;class MyString {
private:char* data;size_t length;public:MyString(const char* str) {length = strlen(str);data = new char[length + 1];strcpy(data, str);}// 深拷贝构造函数MyString(const MyString& other) {length = other.length;data = new char[length + 1];strcpy(data, other.data);}~MyString() {delete[] data;}
};int main() {MyString str1("Hello");MyString str2 = str1; // 深拷贝cout << "str1 的地址: " << &str1 << ", str2 的地址: " << &str2 << endl;cout << "str1 的指针成员地址: " << (void*)str1.data() << ", str2 的指针成员地址: " << (void*)str2.data() << endl;return 0;
}

 在上述自定义的MyString类中,我们实现了深拷贝构造函数,确保两个对象的数据是独立的。

 


💯string 类的操作符重载

(一)赋值操作符(=)

string类重载了赋值操作符,使得可以将一个字符串或字符数组赋值给string对象。例如:

#include <iostream>
#include <string>using namespace std;int main() {string str;str = "Hello";cout << "赋值后的字符串为: " << str << endl;return 0;
}

(二)加法操作符(+)

  • 可以将两个string对象相加,得到一个新的string对象其内容为两个字符串连接后的结果。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str1 = "Hello";string str2 = "World";string str3 = str1 + str2;cout << "相加后的字符串为: " << str3 << endl;return 0;
    }

  • 也可以将一个string对象和一个字符数组或单个字符相加。例如:
    #include <iostream>
    #include <string>using namespace std;int main() {string str1 = "Hello";string str2 = str1 + ", World!";cout << "相加后的字符串为: " << str2 << endl;return 0;
    }

 

(三)下标操作符([])

string类重载了下标操作符,使得可以通过下标访问字符串中的单个字符。例如:

#include <iostream>
#include <string>using namespace std;int main() {string str = "Hello";cout << "字符串中的第 2 个字符为: " << str[1] << endl;return 0;
}

 


💯总结

🌠C++ 的string类是一个功能强大且使用方便的工具,用于处理字符串。它的内部结构、构造函数、成员函数以及操作符重载等特性使得字符串的操作变得更加简单和高效。同时,😊了解浅拷贝和深拷贝的区别对于正确使用string类至关重要。通过深入理解string类的这些方面,我们可以更好地运用它来解决各种编程问题,提高程序的质量和效率。在实际编程中,我们应该充分利用string类的优势,避免一些常见的错误,如越界访问字符串中的字符等。


下篇文章我将模拟实现string类,以解决更复杂编程问题! 

欢迎关注我👉【A Charmer】  

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【EndNote版】如何在Word中引用文献

1、在Word中&#xff0c;鼠标光标放在所需插入文献的位置 2、点击选项卡中的“EndNote X9”&#xff0c;直接在EndNote中选中对应的文献 3、选中文献&#xff0c;点击工具栏中的“引用” 4、最后就可在Word中看到所插入的文献

[面试题]ES6 Javascript

ES6 箭头函数和普通函数有什么区别? 1)定义方式:箭头函数使用箭头(>)语法&#xff0c;省略了 function 关键字。 2)参数处理:如果只有一个参数&#xff0c;箭头函数可以省略括号。 3)函数体:如果函数体只有一条语句&#xff0c;箭头函数可以省略花括号和 return 关键字 4)…

Leetcode 二叉树中的最大路径和

算法思想 这道题要求在一棵二叉树中找到路径和最大的路径。路径可以从树中任意一个节点开始&#xff0c;到任意一个节点结束&#xff0c;但路径上的节点必须是连续的。 算法使用递归的方式来遍历树中的每个节点&#xff0c;并在遍历过程中计算包含当前节点的最大路径和。具体…

计算机视觉实验一:图像基础处理

1. 图像的直方图均衡 1.1 实验目的与要求 (1)理解直方图均衡的原理与作用; (2)掌握统计图像直方图的方法; (3)掌握图像直方图均衡的方法。 1.2 实验原理及知识点 直方图均衡化是通过灰度变换将一幅图象转换为另一幅均衡直方图&#xff0c;即在每个灰度级上都具有相同的象素…

计算结构力学:多自由度振动系统

本文以笔记的形式记录计算结构力学的若干基础知识。 注1&#xff1a;限于研究水平&#xff0c;分析难免不当&#xff0c;欢迎批评指正。 注2&#xff1a;文章内容会不定期更新。 预修1&#xff1a;线性代数 1. 标准特征值 复矩阵Schur分解&#xff1a;对于复矩阵&#xff0c…

Linux基础环境搭建(CentOS7)- 安装Scala和Spark

#Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Scala和Spark Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Scala和Spark 大家注意以下的环境搭建版本号&#xff0c;如果版本不匹配有可能出现问题&#xff01;&#xff08;spark不要下2.4版本的 会报错…

Vue3使用AntV | X6绘制流程图:开箱即用

x6官方地址X6图编辑引擎 | AntV 官方文档仔细地介绍了很多丰富的功能,这里的demo可以满足基本的使用,具体拓展还需要仔细看文档内容 先上效果图 1、安装 通过 npm 或 yarn 命令安装 X6。 # npm npm install @antv/x6 --save# yarn yarn add @antv/x6 初始化画布 <di…

安装使用docker harbor并推送镜像到仓库

1.概要 通过上一章节的讲解&#xff0c;我们基本了解了docker的操作命令&#xff0c;在文章的最后我们成功的推送一个镜像到DockerHub的镜像仓库。从流程上说&#xff0c;操作过程可以说很完美&#xff0c;但是整个推送过程消耗的时间太长&#xff0c;我们消耗了大量时间在访问…

HTML练习题:彼岸的花(web)

展示效果: 代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>彼岸の花</title><style…

thinkphp和vue基于Workerman搭建Websocket服务实现用户实时聊天,完整前后端源码demo及数据表sql

最近接了一个陪玩小程序&#xff0c;其中有一个实时聊天的项目&#xff0c;需要搭建Websocke服务&#xff0c;通过多方考虑选择了通过GatewayWorker框架&#xff08;基于Workerman&#xff09;,将代码提取了出来&#xff0c;用到的框架封装到了vendor目录下&#xff0c;完整前后…

【计算机网络 - 基础问题】每日 3 题(五十八)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

C++ 二叉树进阶:相关习题解析

目录 1. 二叉树创建字符串。 2. 二叉树的分层遍历1 3. 二叉树的分层遍历2 4. 二叉树的最近公共祖先 5. 将二叉搜索树转换为排序的双向链表 6. 从前序与中序遍历序列构造二叉树 7. 从中序与后序遍历序列构造二叉树 8. 二叉树的前序遍历&#xff0c;非递归迭代实现 9.…

云舟观测:基于eBPF监控主机的TCP网络连接

1 背景 机器网络监控信息在日常问题排查中扮演着至关重要的角色&#xff0c;是不可或缺的工具。通过对网络流量的深入分析&#xff0c;我们不仅能有效评估网络性能&#xff0c;还能迅速识别异常行为&#xff0c;例如流量突然激增、未知的数据传输等&#xff0c;这些对于保障网络…

【IC每日一题】

IC每日一题 1&#xff1a;锁存器(latch)、触发器(flip-flop)、寄存器的概念及区别1.1 概念1.2 锁存器的危害1.3 如何避免产生锁存器 2 手撕题&#xff1a;边沿检测2.1 边沿检测(上升沿、下降沿、双边沿)2.1.1 波形图2.1.2 算法步骤2.1.3 代码 2.2 序列模三检测器2.2.1 描述2.2.…

使用 Docker Compose 将数据版 LobeChat 服务端部署

LobeChat 是一个基于 TypeScript 的开源聊天机器人项目&#xff0c;支持本地部署和接入多个大语言模型。本文介绍如何使用 Docker Compose 将 LobeChat 服务端及其数据库部署到生产环境&#xff0c;让您拥有一个私有化的、可定制的 AI 聊天助手。 一、部署前准备 服务器&…

DICOM标准:DICOM服务类详解,了解存储服务类、查询/检索服务类(Q/R Service Class)和工作流管理服务类等原理

目录 一、概述 二、存储服务类&#xff08;Storage Service Class&#xff09; 存储操作&#xff08;C-STORE&#xff09; 确认操作&#xff08;C-STORE-RSP&#xff09; 三、查询/检索服务类&#xff08;Query/Retrieve Service Class&#xff09; 查询操作&#xff08;C…

八,Linux基础环境搭建(CentOS7)- 安装Mysql和Hive

Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Mysql和Hive 大家注意以下的环境搭建版本号&#xff0c;如果版本不匹配有可能出现问题&#xff01; 一、Mysql下载及安装 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Orac…

Virtuoso使用layout绘制版图、使用Calibre验证DRC和LVS

1 绘制版图 1.1 进入Layout XL 绘制好Schmatic后&#xff0c;在原理图界面点击Launch&#xff0c;点击Layout XL进入版图绘制界面。 1.2 导入元件 1、在Layout XL界面左下角找到Generate All from Source。 2、在Generate Layout界面&#xff0c;选中“Instance”&#…

Spring事务的实现方式

前言 Spring的spring-tx模块提供了对事务管理支持&#xff0c;使用Spring事务可以让我们从复杂的事务处理中得到解脱&#xff0c;无需去处理获得连接、关闭连接、事务提交和回滚等这些操作。Spring事务管理是Spring框架提供的一个核心功能&#xff0c;它允许开发者以声明式或编…

线性代数(1)——线性方程组的几何意义

线性代数的基本问题是求解个未知数的个线性方程&#xff1b; 例如&#xff1a;&#xff08;方程1&#xff09;。 在线性代数的第一讲中&#xff0c;我们从Row Picture、Column Picture、Matrix Picture三个角度来看这个问题。 上面的系统是二维的。通过添加第三个变量&#…