【C++】C++ 标准库string类介绍(超详细解析,小白必看系列)
C++ 标准库中的 std::string
类是一个非常强大的工具,用于处理和操作字符串。它属于 <string>
头文件,并提供了一套丰富的功能和方法。以下是 std::string
类的一些主要特性和常用操作:
1 string简介
- 字符串是表示字符序列的类
- 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
- string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信 息,请参阅basic_string)。
- string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits 和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
- 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个 类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结:
- string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
- string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
- 不能操作多字节或者变长字符的序列。
- 在使用string类时,必须包含#include头文件以及using namespace std;
2 string类的常用接口说明
1. 构造函数和赋值操作
- 默认构造函数:创建一个空字符串。
- 带字符串参数的构造函数:可以用 C 风格字符串(如
const char*
)来初始化。 - 拷贝构造函数:用另一个
std::string
对象来初始化。 - 赋值操作符:可以将一个字符串赋值给另一个字符串。
std::string str1; // 默认构造函数
std::string str2 = "Hello, World!"; // 带字符串参数的构造函数
std::string str3 = str2; // 拷贝构造函数
std::string str4;
str4 = "World, Hello!"; // 赋值操作
2. 容量操作
- length() 和 size():返回字符串的长度。
- capacity():返回字符串的容量。
- empty():检查字符串是否为空。
- clear():清空字符串。
- reserve():为字符串预留空间。
- resize():调整字符串的大小。
std::string myString = "Hello, World!";
std::cout << "Length: " << myString.length() << std::endl;
std::cout << "Capacity: " << myString.capacity() << std::endl;
std::cout << "Is empty? " << (myString.empty() ? "Yes" : "No") << std::endl;
myString.clear();
std::cout << "After clear: " << myString << std::endl;
myString.reserve(20);
myString.resize(10, 'X');
std::cout << "After resizing: " << myString << std::endl;
3. 访问及遍历操作
- operator[]:通过下标访问字符串中的字符。
- begin() 和 end():获取字符串的迭代器,用于遍历字符串。
- rbegin() 和 rend():获取字符串的反向迭代器,用于反向遍历字符串。
- 范围 for 循环:C++11 引入的简洁遍历方式。
const std::string myString = "Hello, World!";
char character = myString[7];
std::cout << "Character at position 7: " << character << std::endl;for (auto it = myString.begin(); it != myString.end(); ++it) {std::cout << *it << " ";
}
std::cout << std::endl;for (auto rit = myString.rbegin(); rit != myString.rend(); ++rit) {std::cout << *rit << " ";
}
std::cout << std::endl;
4. 修改操作
- operator+= 和 append():拼接字符串。
- insert():在指定位置插入字符串。
- erase():删除指定位置的字符或子串。
- replace():替换指定位置的字符或子串。
std::string str = "Hello";
str += ", World!";
str.append(" How are you?");
str.insert(5, " there");
str.erase(5, 6);
str.replace(0, 5, "Hi");
std::cout << str << std::endl;
5. 查找操作
- find() 和 rfind():查找子串的位置。
- substr():获取子串。
std::string str = "Hello, World!";
size_t pos = str.find("World");
if (pos != std::string::npos) {std::cout << "Found 'World' at position: " << pos << std::endl;
}
std::string sub = str.substr(7, 5);
std::cout << "Substring: " << sub << std::endl;
6. vs和g++下string结构的说明
在 Visual Studio (VS) 和 GNU Compiler Collection (GCC) 下,std::string
类的实现有一些差异。以下是对这两种环境下 std::string
结构的简要说明:
1 Visual Studio 下的 std::string
结构
在 Visual Studio 中,std::string
类的实现较为复杂,通常包含以下几个部分:
- 指针:指向实际存储字符串数据的内存。
- 大小:表示字符串的长度。
- 容量:表示分配的内存容量。
Visual Studio 使用了 Small String Optimization (SSO) 技术,当字符串较短时,数据会直接存储在对象内部,而不需要额外的动态内存分配。这种优化可以提高性能,减少内存分配的开销
2 GCC 下的 std::string
结构
G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指
- 空间总大小
- 字符串有效长度
- 引用计数
3 写时拷贝的工作原理
- 共享数据:当一个
std::string
对象被复制时,新的对象不会立即复制字符串数据,而是共享原始字符串的数据。这意味着多个std::string
对象可以指向同一块内存。 - 引用计数:每个共享的数据块都有一个引用计数,记录有多少个
std::string
对象共享这块数据。 - 写时复制:当任何一个
std::string
对象试图修改共享的数据时,会先检查引用计数。如果引用计数大于1,表示数据被多个对象共享,此时会创建数据的真实副本,然后对这个副本进行修改。这样,修改操作不会影响其他共享同一数据的对象。
示例代码
以下是一个简单的写时拷贝实现示例:
#include <iostream>
#include <cstring>class String {
public:String(const char* str = "") {if (str) {m_data = new char[strlen(str) + 1];strcpy(m_data, str);m_refCount = new int(1);} else {m_data = new char[1];*m_data = '\0';m_refCount = new int(1);}}String(const String& other) {m_data = other.m_data;m_refCount = other.m_refCount;++(*m_refCount);}~String() {if (--(*m_refCount) == 0) {delete[] m_data;delete m_refCount;}}String& operator=(const String& other) {if (this != &other) {if (--(*m_refCount) == 0) {delete[] m_data;delete m_refCount;}m_data = other.m_data;m_refCount = other.m_refCount;++(*m_refCount);}return *this;}char& operator {if (*m_refCount > 1) {char* newData = new char[strlen(m_data) + 1];strcpy(newData, m_data);--(*m_refCount);m_data = newData;m_refCount = new int(1);}return m_data[index];}const char* c_str() const {return m_data;}private:char* m_data;int* m_refCount;
};int main() {String str1("Hello");String str2 = str1;str2[0] = 'h';std::cout << "str1: " << str1.c_str() << std::endl;std::cout << "str2: " << str2.c_str() << std::endl;return 0;
}
现代 C++ 标准中的变化
在 C++11 及之后的标准中,std::string
类的实现已经不再使用写时拷贝技术。原因包括:
- 线程安全性:写时拷贝需要维护引用计数,这在多线程环境中会引入复杂的同步问题。
- 性能考虑:现代 C++ 标准更倾向于使用移动语义和右值引用来优化性能,而不是依赖写时拷贝
相关文章:
【C++】C++ 标准库string类介绍(超详细解析,小白必看系列)
C 标准库中的 std::string 类是一个非常强大的工具,用于处理和操作字符串。它属于 <string> 头文件,并提供了一套丰富的功能和方法。以下是 std::string 类的一些主要特性和常用操作: 1 string简介 字符串是表示字符序列的类 标准的字…...

若依RuoYi项目环境搭建教程(RuoYi-Vue + RuoYi-Vue3版本)
文章目录 一、开发脚手架选择二、RuoYi框架1、介绍2、版本发展3、为什么选择若依4、优缺点5、项目内置功能 三、后端项目部署1、拉取源码2、环境要求3、Maven构建4、MySQL相关(1)导入SQL脚本(2)配置信息 5、Redis相关(…...

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密
加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30…...

HarmonyOS开发之使用PhotoViewPicker(图库选择器)保存图片
一:效果图 二:添加依赖 import fs from ohos.file.fs;//文件管理 import picker from ohos.file.picker//选择器 三:下载,保存图片的实现 // 下载图片imgUrldownloadAndSaveImage(imgUrl: string) {http.createHttp().request(…...

跨境独立站支付收款常见问题排雷篇1.0丨出海笔记
最近小伙伴们在社群讨论挺多关于独立站支付问题的,鉴于不少朋友刚接触独立站,我整理了一些独立站支付相关的问题和解决方案,供大家参考,百度网上一堆媒体的那些软文大家就别看了,都是软广或者抄来抄去,让大…...

uni-app实现web-view和App之间的相互通信
双向实时 如果app端部署成网站,则web-view就是iframe,使用也可以双向通讯 https://uniapp.dcloud.net.cn/component/web-view.html APP端代码 index.vue: <template><web-viewid"m-webview":fullscreen"true":src"…...

HTB-Vaccine(suid提权、sqlmap、john2zip)
前言 各位师傅大家好,我是qmx_07,今天来为大家讲解Vaccine靶机 渗透过程 信息搜集 服务器开放了 21FTP服务、22SSH服务、80HTTP服务 通过匿名登录FTP服务器 通过匿名登录到服务器,发现backup.zip文件,可能存在账号密码 发现b…...
【达梦数据库】异构数据库迁移到达梦
目录 1、迁移准备2、正式迁移3、问题处理3.1、return附近出现错误3.1.1、排查过程3.1.2、问题原因3.1.2、解决方法 3.2、对象[XXX]处于无效状态-类型13.2.1、排查过程3.2.2、问题原因3.2.3、解决方法 3.3、对象[XXX]处于无效状态-类型23.3.1、排查过程3.3.2、问题原因3.3.3、解…...

抽象类和接口(1)
抽象类: 什么是抽象类: 听着就很抽象,确实挺抽象,先来写一个抽象类感觉一下: 这就是抽象类! 在 Java 中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法…...
epoll内核原理与实现详解
目录 1 epoll相关理论基础 1.1 I/O多路复用技术 1.2 事件驱动模型 1.2.1 基本概念 1.2.2 优缺点分析 1.2.3 与epoll的关联 1.3 epoll机制简介 1.3.1 核心原理 1.3.2 优点 2 epoll内核原理 2.1 epoll数据结构 2.1.1 主要数据结构 2.1.2 数据结构关系 2.2 epoll工作…...

被低估的SQL
SQL是现代数据库管理系统中不可或缺的一部分。尽管它的使用已十分普遍,但在数据处理领域,SQL的某些功能和潜力仍然被许多人低估。接下来,小编将与您一起,探讨SQL的一些被忽视的特性,揭示它在数据管理中的真正实力。 1.…...
数字证书、数字签名及其关系
一.数字证书与数字签名 1.数字证书是一个经证书授权中心数字签名的包含公开密钥拥有者信息以及公开密钥的文件。简单地说,数字证书是一段包含用户身份信息、用户公钥信息以及份验证机构数字签名的数据。 通俗理解:数字证书相当于【身份证】 —— 确认你…...

一文读懂:如何将广告融入大型语言模型(LLM)输出
本文是我翻译过来的,讨论了在线广告行业的现状以及如何将大型语言模型(LLM)应用于在线广告。 原文请参见”阅读原文“。 在2024年,预计全球媒体广告支出的69%将流向数字广告市场。这个数字预计到2029年将增长到79%。在Meta的2024…...
godotenv拜读
简介 应用提倡将配置存储在环境变量中。任何从开发环境切换到生产环境时需要修改的东西都从代码抽取到环境变量里。 但是在实际开发中,如果同一台机器运行多个项目,设置环境变量容易冲突,不实用。godotenv库从.env文件中读取配置,…...

解析REST API与OpenAPI之差异:避免混淆
在网络API领域,常提及的两种术语为Rest API与Open API,其既存在差异亦存在联系。前者是一种API设计方式,后者则是一种API描述及定义规范。值得注意的是,OpenAPI 可用于描述和定义REST API。 什么是REST API? REST API …...

一篇文章就搞懂了:过虑器 、拦截器 、监听器是什么
java 过虑器 、拦截器 、监听器的区别? 实现原理: 过滤器基于函数回调实现。拦截器基于Java的反射机制实现。监听器用于监听特定事件的发生,并作出相应处理。 使用范围: 过滤器依赖于Tomcat等容器,主要用于Web程序。拦截…...

本体映射与本体集成
文章目录 本体映射与本体集成本体映射分类知识挖掘是从己有的实体及实体关系出发挖掘新的知识,具体包括知识内容挖掘和知识结构挖掘。 本体映射与本体集成 解决本体异构的通用方法是本体集成与本体映射。本体集成直接将多个本体合并为一个大本体,本体映射则寻找本体间的映射…...

华媒舍:10种提升推特大V发文推广曝光率的方式
在社交媒体时代,推特已成为许多大V达到更广泛受众的重要渠道。并非所有的推文都能获得理想的曝光率。为了帮助大V们提升推文的曝光率,本文将介绍10种有效的方式。 1. 精心构思内容 好的内容是吸引读者和提升曝光率的关键。大V们应该从听众的角度出发&am…...
前端本地存储数据:深入解析与代码示例(Cookie、LocalStorage、SessionStorage和IndexedDB)
在现代Web应用中,前端本地存储是实现用户个性化体验的关键技术。本文将深入探讨前端本地存储的四种主要技术:Cookie、LocalStorage、SessionStorage和IndexedDB,并提供具体的代码示例。 Cookie 简介 Cookie是由服务器创建并存储在用户浏览…...
Java语言程序设计基础篇_编程练习题*18.21 (将十进制数转换为二进制数)
*18.21 (将十进制数转换为二进制数) 编写一个递归方法,将一个十进制数转换为一个二进制数的字符串。方法头如下: public static String dec2Bin(int value)编写一个测试程序,提示用户输入一个十进制数,然后显示等价的二进制数。 代码示例 …...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...