当前位置: 首页 > news >正文

【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.mrgr.cn/news/61936.html

相关文章:

  • 需要知道的关键字
  • SpringMVC执行流程(视图阶段JSP、前后端分离阶段)、面试题
  • WPF拖拽交互全攻略及实现自定义拖拽控件及数据交换技巧解析
  • 没有对象来和我手撕红黑树吧
  • 【Golang】Golang的数组和slice切片的区别
  • 【解决方案】Mac上禁止chrome自动更新的三种方法
  • python公寓出租管理系统-计算机毕业设计源码00130
  • 项目开发的架构模式与异步请求(AJAX)
  • 香橙派Orangepi 5plus 配置Hailo-8/Hailo-8L
  • 2024 Rust现代实用教程:1.2编译器与包管理工具以及开发环境搭建
  • 荒野大镖客:救赎 PC版整合包
  • 【K8S系列】Kubernetes 中 NodePort 类型的 Service 无法访问的问题【已解决】
  • 基于安卓Android的助农商城系统APP(源码+文档+部署+讲解)
  • Rust 力扣 - 54. 螺旋矩阵
  • 数据结构算法学习方法经验总结
  • git快速合并代码dev->master
  • ECharts 折线图 / 柱状图 ,通用配置标注示例
  • JAVA基础-Map集合
  • 三格电子——RS485转光纤点对点式【MS-F155-M】
  • 数据结构与算法——(Hash)哈希表与哈希算法
  • 【生物学&水族馆】金鱼成体幼苗检测活体识别系统源码&数据集全套:改进yolo11-Parc
  • 打工人不上班之后,躺平还是躺赢?
  • 数据结构和算法-动态规划(3)-经典问题
  • 自闭症摘帽:突破束缚的新方式
  • YOLO即插即用模块--PPA
  • 【LeetCode】两数之和、大数相加