【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)编写一个测试程序,提示用户输入一个十进制数,然后显示等价的二进制数。 代码示例 …...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
