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

【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.kler.cn/a/371807.html

相关文章:

  • 3D Gaussian Splatting代码详解(一):模型训练、数据加载
  • 大语言模型及LangChain介绍
  • Depcheck——专门用于检测 JavaScript 和 Node.js 项目中未使用依赖项的工具
  • Spring Boot技术中小企业设备管理系统设计与实践
  • LiNo论文解析
  • Kubernetes固定Pod IP和Mac地址
  • python如何完成金融领域的数据分析,思路以及常见的做法是什么?
  • 【Django】创建项目、启动及app过程及遇到的问题和解决方案
  • Firefox和Chrome谁的插件生态系统更完善
  • 8年经验之谈 —— 如何使用自动化工具编写测试用例?
  • Java基础(4)——构建字符串(干货)
  • 结合Intel RealSense深度相机和OpenCV来实现语义SLAM系统
  • 开源AI助力医疗革新:OCR系统与知识图谱构建
  • 大厂物联网(IoT)高频面试题及参考答案
  • HTML入门教程7:HTML样式
  • Go 读取xls文件 (shakinm/xlsReader/xls)
  • 消息队列-Rabbitmq(消息发送,消息接收)
  • 爬虫设计思路
  • ‘cmd‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
  • 【SQLite】改善默认输出格式不直观难以阅读问题:通过修改输出设置提升数据可读性
  • 【http作业】
  • Chrome异步编程
  • 深度学习数学基础之链式法则
  • 星巴克们需要找回节奏
  • 边缘计算【智能+安全检测】系列教程--agx orin解决RTC时间问题
  • python 轮子是什么