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

news2024/11/26 22:17:18

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

 


目录

💯前言

💯为什么要学习 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.coloradmin.cn/o/2228132.html

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

相关文章

卷积神经网络实验三:模型优化(1)

作者有话说&#xff1a; 这篇文章写的还是比混乱的。因为本人也是第一次做这样的尝试&#xff0c;虽然接触深度学习有一年了&#xff0c;但是对于模型的优化仅仅是局限于理论上。通过这一次的实验&#xff0c;我对于模型的理解也更深了几分。我不期望这篇文章能帮你能解决多大问…

clickhouse运维篇(三):生产环境一键生成配置并快速部署ck集群

前提条件&#xff1a;先了解集群搭建流程是什么样&#xff0c;需要改哪些配置&#xff0c;有哪些环境&#xff0c;这个文章目的是简化部署。 clickhouse运维篇&#xff08;一&#xff09;&#xff1a;docker-compose 快速部署clickhouse集群 clickhouse运维篇&#xff08;二&am…

嵌入式浏览器 -- Chromium VS Firefox

嵌入式浏览器概念 嵌入式浏览器是嵌入式系统中的核心组件之一&#xff0c;用于为设备提供网络访问能力和内容显示功能。与传统PC浏览器相比&#xff0c;嵌入式浏览器更加注重性能优化和资源效率&#xff0c;同时确保核心功能可用&#xff0c;如HTML渲染、JavaScript支持和多媒…

CSP-J2024入门级T3:小木棍

题目链接 CSP-J2024T3:小木棍 题目描述 小 S 喜欢收集小木棍。在收集了 n n n 根长度相等的小木棍之后,他闲来无事,便用它们拼起了数字。用小木棍拼每种数字的方法如下图所示。 现在小 S 希望拼出一个正整数,满足如下条件: 拼出这个数恰好使用

Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程

Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程 Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程前言 OpenCV概述核心功能优势特点应用领域安装与使用 OpenCV_contrib概述核心功能具体模块 安装与使用一、准备工作二、下载OpenCV和OpenCV_contrib三、编译和安装OpenCV四、…

shodan5,参数使用,批量查找Mongodb未授权登录,jenkins批量挖掘

查找美国安全局漏洞 nww.nsa.gov&#xff08;美国安全局官方网站) net参数使用 搜索指定的ip网段 shodan search --limit 10 --fields ip_str,port net:208.88.84.0/24 (老美国家安全局的一个网段)可能直接访问不太行&#xff0c;可以使用host参数&#xff0c;得到域名再去…

nrm的使用

在安装nrm之前&#xff0c;要先完成node.js的安装。 1、nrm的介绍 ‌nrm&#xff08;npm registry manager&#xff09;是一个npm源管理器&#xff0c;允许用户在不同npm源之间快速切换。 关于npm和nvm的介绍&#xff0c;详见文章nvm的使用-CSDN博客。 解释&#xff1a;比如…

图片懒加载(自定义指令)

----------------------------------------------------------- 图片懒加载自定义指令使用mock模拟随机图片列表组件如下&#xff08;主要内容&#xff09;&#xff1a;配置自定义指令 图片懒加载 实现思路 使用自定义指令实现通用图片懒加载&#xff08;在图片到达视口内时再…

socket编程---UDP

目录 一、socket 二、socket接口 1.流程原理 2.代码 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; socket编程又称套接字编程&#xff0c;指进行网络通信程序的编写 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、soc…

R语言机器学习算法实战系列(十四): CatBoost分类算法+SHAP值 (categorical data gradient boosting)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍CatBoost的原理CatBoost的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割设置数据对象调节参数训练模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC Curv…

创建ODBC数据源SQLConfigDataSource函数的用法

网络上没有这个函数能实际落地的用法说明&#xff0c;我实践后整理一下&#xff1a; 1.头文件与额外依赖库&#xff1a; #include <odbcinst.h> #pragma comment(lib, "legacy_stdio_definitions.lib") 2.调用函数&#xff1a; if (!SQLConfigDataSourceW(…

HCIP-HarmonyOS Application Developer V1.0 笔记(一)

HarmonyOS的系统特性 硬件互助&#xff0c;资源共享;一次开发&#xff0c;多端部署;统一OS&#xff0c;弹性部署。 分布式软总线&#xff1a;分布式任务调度、分布式数据管理、分布式硬件虚拟化的基座 18N的独立设备 1个手机&#xff0c;8种设备&#xff08;车机&#xff0c…

upload-labs靶场Pass-21

upload-labs靶场Pass-21 本关上传方法众多&#xff0c;但是应该考察的是数组后缀绕过&#xff0c;所以我的上传围绕此展开 1.分析源码 $is_upload false; // 初始化上传状态为false $msg null; // 初始化消息变量为null// 检查是否有文件上传 if(!empty($_FILES[upload_fi…

【undefined reference to xxx】zookeeper库编译和安装 / sylar项目ubuntu20系统编译

最近学习sylar项目&#xff0c;编译项目时遇到链接库不匹配的问题&#xff0c;记录下自己解决问题过程&#xff0c;虽然过程很艰难&#xff0c;但还是解决了&#xff0c;以下内容供大家参考&#xff01; undefined reference to 问题分析 项目编译报错 /usr/bin/ld: ../lib/lib…

网络服务ssh

Linux 网络基础 一、知识回顾 网络地址&#xff1a;互联网协议地址&#xff08;IP地址&#xff09;为互联网上每一个网络或主机分配一个逻辑地址&#xff0c;IP地址工作在网络层。 ​ IP的分类&#xff1a;IPV4 IPV6 物理地址&#xff1a;物理地址&#xff08;MAC地址&…

Git获取本地仓库和常用指令

一、获取本地仓库 1&#xff09;在电脑的任意位置创建一个空目录&#xff08;例如test01&#xff09;作为我们的本地Git仓库 2&#xff09;进入这个目录中&#xff0c;点击右键打开Git bash窗口 3&#xff09;执行命令git init&#xff08;初始化当前目录为一个git仓库&…

解决报错:JDK版本不正确

加载maven过程中&#xff0c;控制台报错&#xff1a; Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.…

Webserver(1.8)操作函数

目录 文件属性操作函数access函数chmod函数chown函数truncate函数 目录操作函数mkdir函数rmdir函数rename函数chdir函数*getcwd函数 目录遍历函数*opendir函数*readdir函数closedir函数 dup、dup2函数dupdup2 fcntl函数 文件属性操作函数 access函数 判断某个文件是否有某个权…

解决ElasticSearch启动成功却无法在浏览器访问问题

目录 前言&#xff1a; 问题复现 &#xff1a; 解决问题&#xff1a; 1、修改sysctl.conf文件 2、在sysctl.conf文件增加这段东西 3、 然后保存退出&#xff0c;输入以下命令使其生效 结语&#xff1a; 前言&#xff1a; 这篇文章是小白我今天突然启动es&#xff0c;发现e…

【tomcat系列漏洞利用】

Tomcat 服务器是一个开源的轻量级Web应用服务器&#xff0c;在中小型系统和并发量小的场合下被普遍使用。主要组件&#xff1a;服务器Server&#xff0c;服务Service&#xff0c;连接器Connector、容器Container。连接器Connector和容器Container是Tomcat的核心。一个Container…