【C++】string

文章目录

  • 1. 标准库中的string类
    • 1.1 string类
  • 2 string类的常用接口说明
    • 2.1 string类对象的常见构造
    • 2.2 string类对象的容量操作
    • 2.3. string类对象的访问及遍历操作
    • 2.4 string类对象的修改操作
    • 2.5 string类非成员函数
    • 2.6 vs和g++下string结构的说明


1. 标准库中的string类

1.1 string类

string类的文档介绍

  1. 字符串是表示字符序列的类。
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型)。
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数。
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或边长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

总结

  1. string是表示字符串的字符串类。
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, alloctor>string;
  4. 不能操作多字节或者变长字符的序列。
  5. 在使用string类时,必须包含#include头文件以及using namespace std;

2 string类的常用接口说明

2.1 string类对象的常见构造

(constructor)函数名称功能说明
string()(重点)构造空的string类对象,即空字符串
string(const char* s)(重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string& s)(重点)拷贝构造函数
void Teststring()
{string s1;					// 构造空的string类对象s1string s2("hello bit");		// 用C格式字符串构造string类对象s2string s3(s2);				// 拷贝构造s3
}

2.2 string类对象的容量操作

函数名称功能说明
size(重点)返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty(重点)检测字符串是否为空串,是返回true,否则返回false
clear(重点)清空有效字符
reserve(重点)为字符串预留空间
resize(重点)将有效字符的个数改成n个,多出的空间用字符c填充

代码演示

// 测试string容量相关的接口
// size/clear/resize
void Teststring1()
{// 注意:string类对象支持直接用cin和cout进行输入和输出string s("hello, string!");cout << s.size() << endl;cout << s.length() << endl;cout << s.capacity() << endl;cout << s << endl << endl;// 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小s.clear();cout << s.size() << endl;cout << s.capacity() << endl << endl;// 将s中有效字符个数增加到10个,多出位置用'a'进行填充// “aaaaaaaaaa”s.resize(10, 'a');cout << s.size() << endl;cout << s.capacity() << endl << endl;// 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充// "aaaaaaaaaa\0\0\0\0\0"// 注意此时s中有效字符个数已经增加到15个s.resize(15);cout << s.size() << endl;cout << s.capacity() << endl;cout << s << endl << endl;// 将s中有效字符个数缩小到5个s.resize(5);cout << s.size() << endl;cout << s.capacity() << endl;cout << s << endl;
}//====================================================================================
void Teststring2()
{string s;// 测试reserve是否会改变string中有效元素个数(不会改变)s.reserve(100);cout << s.size() << endl;cout << s.capacity() << endl << endl;// 测试reserve参数小于string的底层空间大小时,是否会将空间缩小(不会缩小)s.reserve(50);cout << s.size() << endl;cout << s.capacity() << endl;
}// 利用reserve提高插入数据的效率,避免增容带来的开销
//====================================================================================

注意:

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3. resize(size_t n)与resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(size_t n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。
    注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg = 0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

2.3. string类对象的访问及遍历操作

函数名称功能说明
operator[](重点)返回pos位置的字符
begin + endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin + rend反向迭代器
范围forC++11支持更简洁的范围for的新遍历方式

代码演示

// string的遍历
// begin()+end()   for+[]  范围for
// 注意:string遍历时使用最多的还是for+下标 或者 范围for(C++11后才支持)
// begin()+end()大多数使用在需要使用STL提供的算法操作string时,比如:采用reverse逆置string
void Teststring3()
{string s1("hello string");const string s2("Hello string");cout << s1 << " " << s2 << endl;cout << s1[0] << " " << s2[0] << endl;s1[0] = 'H';cout << s1 << endl;// s2[0] = 'h';   代码编译失败,因为const类型对象不能修改
}void Teststring4()
{string s("hello string");// 3种遍历方式:// 需要注意的以下三种方式除了遍历string对象,还可以遍历时修改string中的字符,// 另外以下三种方式对于string而言,第一种使用最多// 1. for+operator[]for (size_t i = 0; i < s.size(); ++i)cout << s[i];cout << endl;// 2.迭代器string::iterator it = s.begin();while (it != s.end()){cout << *it;++it;}cout << endl;// string::reverse_iterator rit = s.rbegin();// C++11之后,直接使用auto定义迭代器,让编译器推导迭代器的类型auto rit = s.rbegin();while (rit != s.rend()){cout << *rit;++rit;}cout << endl;// 3.范围forfor (auto ch : s)cout << ch;cout << endl;
}

2.4 string类对象的修改操作

函数名称功能说明
push_back在字符串后尾插字符c
appebd在字符串后追加一个字符串
operator+=(重点)在字符串后追加字符串str
c_str(重点)返回C格式字符串
find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

代码演示

// 测试string:
// 1. 插入(拼接)方式:push_back  append  operator+= 
// 2. 正向和反向查找:find() + rfind()
// 3. 截取子串:substr()
// 4. 删除:erase
void Teststring5()
{string str;str.push_back(' ');				// 在str后插入空格str.append("hello");			// 在str后追加一个字符串"hello"str += 's';						// 在str后追加一个字符's'   str += "tring";					// 在str后追加一个字符串"tring"cout << str << endl;cout << str.c_str() << endl;	// 以C语言的方式打印字符串cout << endl;// 获取file的后缀string file("string.cpp");size_t pos = file.rfind('.');string suffix(file.substr(pos, file.size() - pos));cout << suffix << endl;cout << endl;// npos是string里面的一个静态成员变量// static const size_t npos = -1;// 取出url中的域名string url("http://www.cplusplus.com/reference/string/string/find/");cout << url << endl;size_t start = url.find("://");if (start == string::npos){cout << "invalid url" << endl;return;}start += 3;size_t finish = url.find('/', start);string address = url.substr(start, finish - start);cout << address << endl;// 删除url的协议前缀pos = url.find("://");url.erase(0, pos + 3);cout << url << endl;
}

注意:

  1. 在string尾部追加字符时,s.push_back(c)、s.append(1, c)、s += ‘c’ 三种的实现方式差不多,一般情况下string类的 += 操作用的比较多,+= 操作不仅可以连接单个字符,还可以连接字符串。
  2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

2.5 string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>>(重点)输入运算符重载
operator<<(重点)输出运算符重载
getline(重点)获取一行字符串
relational operators(重点)大小比较

2.6 vs和g++下string结构的说明

注意:下述结构是在32位平台下进行验证,32位平台下指针占4个字节。

  • vs下string的结构
    string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字符串的存储空间:
    • 当字符串长度小于16时,使用内部固定的字符数组来存放
    • 当字符串长度大于等于16时,从堆上开辟空间
union _Bxty
{// storage for small buffer or pointer to larger onevalue_type _Buf[_BUF_SIZE];pointer _Ptr;char _Alias[_BUF_SIZE];	// to permit aliasing
} _Bx;

这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。

其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量
最后:还有一个指针做一些其他事情。

故总共占16+4+4+4=28个字节。
在这里插入图片描述

  • g++下string的结构
    g++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指针将来指向一块堆空间,内部包含了如下字段:
    • 空间总大小
    • 字符串有效长度
    • 引用计数
    • 指向堆空间的指针,用来存储字符串
struct _Rep_base
{size_type _M_length;size_type _M_capacity;_Atomic_word _M_refcount;
};

本文完

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/224471.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis缓存穿透、缓存击穿、缓存雪崩介绍

一、Redis的缓存穿透 1.什么是缓存穿透&#xff1f; 缓存穿透是指&#xff1a;客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这时缓存就永远不会生效&#xff0c;这些请求都打到数据库从而导致数据库压力过大。 2.出现缓存穿透的解决方案&#xff0c;以下是常用的两…

Matlab仿真2ASK/OOK、2FSK、2PSK、QPSK、4QAM在加性高斯白噪声信道中的误码率与归一化信噪比的关系

本文为学习所用&#xff0c;严禁转载。 本文参考链接 https://zhuanlan.zhihu.com/p/667382398 QPSK代码及高斯白噪声如何产生 https://ww2.mathworks.cn/help/signal/ref/butter.html 滤波器 https://www.python100.com/html/4LEF79KQK398.html 低通滤波器 本实验使用matlab仿…

Node.js(二)-模块化

1. 模块化的基本概念 1.1 什么是模块化 模块化是指解决一个复杂问题时&#xff0c;自顶向下逐层将系统拆分成若干模块的过程。对于整个系统来说&#xff0c;模块是可组合、分解和更换的单元。 1.2 编程领域中的模块化 编程领域中的模块化&#xff0c;就是遵守固定的规则&…

解决log4j多个日志都写到一个文件

之前客户端程序由于Websockt包依赖的log4j&#xff0c;就用log4j写日志了&#xff0c;Web用的log4j2没毛病。用log4j的多个logger的日志都写到一个文件里了&#xff0c;查了很多资料都没解决。今天闲了解决一下。 最后好使的配置 # 设置日志根 log4j.rootLogger INFO,Except…

谷歌Gemini造假始末

&#x1f4a1;大家好&#xff0c;我是可夫小子&#xff0c;《小白玩转ChatGPT》专栏作者&#xff0c;关注AIGC、读书和自媒体。 在过去一年中&#xff0c;OpenAI ChatGPT引发了一股AI新浪潮&#xff0c;而谷歌则一直处于被压制的状态&#xff0c;迫切需要一款现象级的AI产品来…

Mysql(2)

目录 一.外键约束属性 创建主键表&#xff1a; ​编辑 创建外键表&#xff1a; 插入数据&#xff0c;先插入主表在插入外表&#xff1a; 删数数据记录时&#xff0c;要先从表再主表&#xff1a; 删除外键属性&#xff1a; 二.数据库的用户权限管理 看数据库中的用户&a…

Flutter详解及案例代码

概念 Flutter是由Google开发的开源UI框架&#xff0c;旨在快速构建高质量的移动应用程序。与传统的移动应用开发方式不同&#xff0c;Flutter使用单一代码库构建应用程序&#xff0c;可以同时在iOS和Android上运行。 Flutter的核心是使用Dart语言编写的&#xff0c;并且具有自…

C语言操作符if语句好习惯 详解分析操作符(详解4)

各位少年&#xff1a; 前言 还记得我们上一章讲过一个比较抽象的代码&#xff0c;它要比较两次都是真的情况下才能打印&#xff0c;那么很显然这样写代码是有弊端的&#xff1f;哪我们C语言之父丹尼斯.里奇&#xff0c;先介绍一下上次拉掉了if语句的好习惯 好再分享一些操作符…

大数据Doris(三十九):Duplicate 模型中的 ROLLUP

文章目录 Duplicate 模型中的 ROLLUP 一、前缀索引

SPFA算法总结

知识概览 SPFA算法是Bellman_Ford算法的优化。时间复杂度一般是O(m)&#xff0c;最坏时间复杂度是O(nm)&#xff08;遇到网格图、菊花图&#xff09;&#xff0c;其中n是点数&#xff0c;m是边数。SPFA算法其实是单源最短路限制最小的算法&#xff0c;只要图中没有负环&#xf…

C++ Qt开发:Charts绘制各类图表详解

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍TreeWidget与QCharts的常用方法及灵活运用。 …

Java之Synchronized与锁升级

Synchronized与锁升级 一、概述 在多线程并发编程中 synchronized 一直是元老级角色&#xff0c;很多人都会称呼它为重量级锁。但是&#xff0c;随着 Java SE 1.6 对 synchronized 进行了各种优化之后&#xff0c;有些情况下它就并不那么重了。 本文详细介绍 Java SE 1.6 中为…

《运维人员的未来:IT界的“万金油“如何继续闪耀光芒》

文章目录 每日一句正能量前言35岁被称为运维半衰期&#xff0c;究竟为何&#xff1f;如何顺利过渡半衰期运维的职业发展路径后记 每日一句正能量 凡事顺其自然&#xff0c;遇事处于泰然&#xff0c;得意之时淡然&#xff0c;失意之时坦然&#xff0c;艰辛曲折必然&#xff0c;历…

详解Java反射机制reflect(一学就会,通俗易懂)

1.定义 #2. 获取Class对象的三种方式 sout(c1)结果为class com.itheima.d2_reflect.TestClass 获取到了Class对象就相当于获取到了该类 2.获取类的构造器 3.获取全部构造器对象 2.根据参数类型获取构造器对象 类型后必须加.class 3.构造器对象调用构造器方法 4.暴力访问 4.获…

Maven私服

1 Maven私服简介 Maven 私服是一种特殊的Maven远程仓库&#xff0c;它是架设在局域网内的仓库服务&#xff0c;用来代理位于外部的远程仓库&#xff08;中央仓库、其他远程公共仓库&#xff09;。 1.1 下载构件顺序 建立私服后&#xff0c;当局域网内的用户需要某个构件时&a…

图灵日记之java奇妙历险记--输入输出方法数组

目录 输入输出输出到控制台从键盘输入使用 Scanner 读取字符串/整数/浮点数使用 Scanner 循环读取 猜数字方法方法定义方法调用的执行过程实参和形参的关系(重要)方法重载 数组数组的创建数组的初始化动态初始化静态初始化 数组的使用元素访问遍历数组 数组是引用类型null数组应…

esp32-s3训练自己的数据进行目标检测、图像分类

esp32-s3训练自己的数据进行目标检测、图像分类 一、下载项目二、环境三、训练和导出模型四、部署模型五、存在的问题 esp-idf的安装参考我前面的文章&#xff1a; esp32cam和esp32-s3烧录human_face_detect实现人脸识别 一、下载项目 训练、转换模型&#xff1a;ModelAssist…

Django之DRF框架三,序列化组件

一、序列化类的常用字段和字段参数 常用字段 字段名字段参数CharFieldmax_lengthNone, min_lengthNone, allow_blankFalse, trim_whitespaceTrueIntegerFieldmax_valueNone, min_valueNoneFloatFieldmax_valueNone, min_valueNoneBooleanFieldNullBooleanFieldFloatFieldmax_…

sql_lab之sqli注入中的cookie注入

Cookei注入&#xff08;gxa的从cookei注入&#xff09; 1.打开控制台 2.验证id2时的值 document.cookie"id2" 3.判断是上面闭合方式 document.cookie"id2 -- s" 有回显 说明是’单引号闭合 4.用order by 判断字段数 5.用联合查询判断回显点 接下来的…

复分析——第1章——复分析准备知识(E.M. Stein R. Shakarchi)

第一章 复分析准备知识 (Preliminaries to Complex Analysis) The sweeping development of mathematics during the last two centuries is due in large part to the introduction of complex numbers; paradoxically, this is based on the seemingly absurd no…