C++ string 全面指南

C++ string 全面指南

一、模板

1. 函数模板

什么是模板呢模板就是一个模具,只需要往这个模具里倒入不同的材料,就可以获得不同材料的铸件

如果我们要实现一个交换函数呢?这是很容易的事情。

在这里插入图片描述

但是这种交换函数只能实现整型之间的交换,如果我想进行浮点数交换呢,字符型交换呢?是不是就不可以了。

虽然我们可以通过函数重载实现不同的交换函数,但是这样做太浪费时间了,没有意义。毕竟只是改变了交换函数参数的类型,代码不需要变化。所以,这种方法是有缺陷的。

1.代码复用率低

2.可维护性差

所以,有了函数模板,这是实现泛型编程的基础

所谓泛型编程就是编写与类型无关的通用代码,是代码复用的一种手段

在这里插入图片描述

template<typename T>就是定义了一个模板,通过一份代码就可以实现多个要求

这里的typename也可以换成class,这两个的区别会在后面讲解。

这个就叫做函数模板函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本

函数模板的格式template<typename T1, typename T2, ..., typename Tn>

2. 函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以,其实模板就是将本来应该我们重复性做的工作交给了编译器

在这里插入图片描述

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用

3. 函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化

模板参数实例化分为隐式实例化和显示实例化

.隐式实例化让编译器根据实参推演模板参数的实际类型

在这里插入图片描述


在这里插入图片描述

.显示实例化:在函数名后的<>中指定模板参数的实际类型

在这里插入图片描述

4. 模板参数的匹配原则

.一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以实例化为这个非模板函数

在这里插入图片描述

.对于非模板函数和同名函数模板,如果其它条件相同,在调用时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生出一个更好匹配的函数,那么将选择模板

在这里插入图片描述

.模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

5. 类模板

.类模板的定义格式

template<classT1,classT2,...,classTn>class 类模板名 {//类内成员定义};
在这里插入图片描述

.类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类

// Stack是类名,Stack<int>才是类型 Stack<int> st1;// int Stack<double> st2;// double

二、STL简介

什么是STL呢

STL是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架

那么,我们需要学习STL的哪些部分呢

在这里插入图片描述

主要学习五个部分,空间配置器直接使用即可

三、String

学习string从两方面去学习,一个是了解string类的接口,另一个便是模拟实现string

在这里插入图片描述

string是被 typedef 的真名叫做basic_string<char>,是用来存储字符的

1. constructor

//构造函数,最常用的几个default(1)string();//无参构造copy(2)string(const string& str);//拷贝构造 from c-string(4)string(constchar* s);//字符串构造//不太常用的//从pos位置开始,拷贝str字符串的后len个字符,如果str字符串//太短或者len为npos,那就从pos位置拷贝到str字符串末尾substring(3)string(const string& str, size_t pos, size_t len = npos);//拷贝s指向的字符数组的前n个字符 from sequence(5)string(constchar* s, size_t n);//用n个连续的字符c的拷贝填充stringfill(6)string(size_t n,char c);
在这里插入图片描述
//赋值string(1) string&operator=(const string& str);
在这里插入图片描述

2. Iterators

//如果string对象是一个const类型的,函数返回const_iterator,否则,返回iterator//普通迭代器 iterator begin();//指向字符串的开始 iterator end();//指向字符串的末尾(最后一个字符的下一个位置)//const迭代器 const_iterator begin()const; const_iterator end()const;//反向迭代器//反向迭代器指向string的反向开始位置(也就是string的末尾最后一个字符) reverse_iterator rbegin(); const_reverse_iterator rbegin()const;//指向string的末尾的反向(也就是string的第一个字符的前一个位置) reverse_iterator rend(); const_reverse_iterator rend()const;
在这里插入图片描述

迭代器可以理解成像指针一样,但是迭代器不是指针

3. Capacity

//size和length两个函数的功能是一致的//字符串的字节数 size_t size()const; size_t length()const;//字符串的容量 size_t capacity()const;//清空字符串voidclear();//判断字符串是否为空,length为0返回true,否则,返回falseboolempty()const;//n代表新的字符串的长度,c是用来填充字符串中新的字符空间的字符//如果n小于当前字符串的长度,字符串会缩短至前n个字符,删除第//n个字符之后的所有字符//如果n大于当前字符串的长度,在字符串的末尾插入字符到n个//(c是一个具体的字符,就用c来初始化,否则就用空字符初始化)voidresize(size_t n);voidresize(size_t n,char c);//请求调整字符串的容量,适应将字符串的长度更改为最多n个字符的需求//如果n > str.capacity,容器的容量会增加到n个字符(capacity >= n)//其它情况,缩小字符串的容量是一个非强制性的请求//这个函数不会影响字符串的长度和内容,也就是说即使缩容也不会//比字符串的长度小voidreserve(size_t n =0);//减少字符串的容量去适应它的size//不影响字符串的长度和内容voidshrink_to_fit();

shrink_to_fit通常是异地缩容,因为无法从内存块的中间释放一部分内存

在这里插入图片描述


在这里插入图片描述

这是在vs上运行的结果,是没有缩容的,那么,看一下g++编译器会不会进行缩容呢

在这里插入图片描述

g++下也是没有缩容的。是否缩容,取决于平台

4. Element access

//返回在字符串中pos位置的字符的引用char&operator[](size_t pos);constchar&operator[](size_t pos)const;//与[]的功能一样,这也是为什么string被吐槽的原因,设计了太//多的函数,有些函数功能是一样的,重点掌握[]的使用char&at(size_t pos);constchar&at(size_t pos)const;//返回的是字符串中最后一个字符的引用char&back();constchar&back()const;//返回的是字符串中第一个字符的引用char&front();constchar&front()const;
在这里插入图片描述

5. Modifiers

//在字符串的末尾追加另一个std::string str对象string(1) string&operator+=(const string& str);//字符串的末尾追加C风格的s字符串 c-string(2) string&operator+=(constchar* s);//在字符串的末尾追加单个字符character(3) string&operator+=(char c);
//追加str的拷贝string(1) string&append(const string& str);//从str的subpos位置开始,拿取sublen个字符,追加到string//的对象中,如果str太短或者sublen等于npos,那就取到str的//末尾substring(2) string&append(const string& str, size_t subpos, size_t sublen);//s指向的以空字符结尾的字符序列,追加到string对象中 c-string(3) string&append(constchar* s);//取s指向的字符数组前n个字符,追加到string对象中buffer(4) string&append(constchar* s, size_t n);//n个字符c的拷贝,追加到string对象中fill(5) string&append(size_t n,char c);
//在string对象的末尾添加字符c,string对象的长度增加1voidpush_back(char c);//删除string对象的最后一个字符,string对象的长度减1voidpop_back();
//在pos位置插入str的拷贝string(1) string&insert(size_t pos,const string& str);//从str中的subpos位置开始,取sublen个字符,插入到string//对象中,如果str太短或者sublen等于npos,就从subpos位置//开始一直到str字符串的末尾substring(2) string&insert(size_t pos,const string& str, size_t subpos, size_t sublen);//s指向的以空字符结尾的字符序列,插入到string对象中 c-string(3) string&insert(size_t pos,constchar* s);//s指向的字符数组的前n个字符的拷贝插入到string对象中buffer(4) string&insert(size_t pos,constchar* s, size_t n);//插入字符c的n次拷贝fill(5) string&insert(size_t pos, size_t n,char c);
//从pos位置开始,删除string的len个字符,如果string太短或者len为npos,就删到string的末尾。//注意,该函数默认删除string的所有字符sequence(1) string&erase(size_t pos =0, size_t len = npos);
//从string对象中的pos位置,用str字符串替换掉string对象中的len个字符 string&replace(size_t pos, size_t len,const string& str);
//拷贝str字符串赋值给string对象string(1) string&assign(const string& str);
在这里插入图片描述

insert,erase,replace需慎用,因为string的底层是数组,在插入,删除,数据时,都需要移动数据,这也就意味着时间复杂度为O(N),而替换数据,如果替换的字符串和 len 是相等的,那还是很高效的,但是如果不相等,也需要移动数据,时间复杂度也为O(N)

//得到一个C风格的字符串constchar*c_str()const;//从pos位置开始查找一个string对象string(1) size_t find(const string& str, size_t pos =0)const;//从pos位置开始查找一个字符串 c-string(2) size_t find(constchar* s, size_t pos =0)const;//从pos位置查找s指向的字符数组的前n个字符buffer(3) size_t find(constchar* s, size_t pos, size_t n)const;//从pos位置查找单个字符character(4) size_t find(char c, size_t pos =0)const;//反向查找,与find的功能是一样的,只不过一个从string的开头处查找,一个从string的末尾查找string(1) size_t rfind(const string& str, size_t pos = npos)const; c-string(2) size_t rfind(constchar* s, size_t pos = npos)const;buffer(3) size_t rfind(constchar* s, size_t pos, size_t n)const;character(4) size_t rfind(char c, size_t pos = npos)const;//在字符串中查找第一个出现在指定字符集合中的字符//成功返回第一个匹配字符的位置,失败返回nposstring(1) size_t find_first_of(const string& str, size_t pos =0)const;
//从pos位置开始取len个字符组成一个子串,构造一个新的string对象并返回(或者到字符串的末尾,如果len大于从pos位置开始剩余字符的长度) string substr(size_t pos =0, size_t len = npos)const;
//从pos位置开始,拷贝string对象中的len个字符,存储在s指向的字符数组里 size_t copy(char* s, size_t len, size_t pos =0)const;

npos是一个 size_t 类型,值为 -1,实际值是一个无穷大的数,因为 size_t 是一个无符号整型

在这里插入图片描述
在这里插入图片描述

6. Non-member function

//获取一行字符//is输入流对象,str存储字符的字符串对象,delim提取字符的分割符(1)istream&getline(istream& is, string& str,char delim);(2)istream&getline(istream& is, string& str);
在这里插入图片描述

今天的文章分享到此结束,觉得不错的小伙伴给个一键三连吧。

Read more

Java 实战:Qoder 数据采集卡快速上手(数据采集 / 配置核心代码)

Java 实战:Qoder 数据采集卡快速上手(数据采集 / 配置核心代码)

在工业控制、数据监测等场景中,Qoder 数据采集卡凭借稳定的性能、丰富的接口,成为硬件数据采集的常用选择。Java 作为跨平台编程语言,通过 Qoder 提供的 JNI 驱动或 SDK,可轻松实现采集卡的设备连接、参数配置、数据采集与存储等核心操作。本文将以 “快速上手” 为目标,带大家用 Java 语言操作 Qoder 数据采集卡,全程代码精简可直接复用,覆盖从环境搭建到实战落地的全流程,新手也能轻松掌握。 一、核心概念与对接逻辑 1. 关键术语说明 术语 核心作用 Qoder 数据采集卡 硬件设备,支持模拟量输入 / 输出、数字量输入 / 输出、计数器等功能 JNI 驱动 Qoder 提供的 Java Native Interface 驱动,

By Ne0inhk

mPLUG多模态开发:Java SpringBoot后端集成实战

mPLUG多模态开发:Java SpringBoot后端集成实战 1. 引言 想象一下这样的场景:电商平台的商品审核团队每天需要处理成千上万的商品图片,人工检查图片内容是否合规、分类是否准确,不仅效率低下,还容易出错。传统的关键词匹配和规则引擎已经无法满足日益复杂的多模态内容理解需求。 这就是mPLUG多模态模型能够大显身手的地方。通过视觉问答能力,它可以准确理解图片内容,回答关于图像的各类问题。但在实际业务中,如何将这种AI能力无缝集成到现有的Java企业系统中,却是一个实实在在的挑战。 本文将带你一步步实现mPLUG在Java SpringBoot后端系统中的完整集成方案,涵盖RESTful API设计、异步任务处理、结果缓存等核心模块,让你能够在电商商品识别等实际场景中快速落地多模态AI能力。 2. mPLUG多模态能力概述 2.1 核心功能特点 mPLUG作为一个强大的多模态模型,最突出的能力就是视觉问答。给定一张图片和一个问题,它能够基于图片内容给出准确的答案。比如你上传一张商品图片并询问"这是什么商品?",mPLUG能够识别出这是"运动鞋"还是"笔记本电脑

By Ne0inhk
Java Web 搭建疫情管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

Java Web 搭建疫情管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 新冠疫情爆发以来,全球公共卫生体系面临前所未有的挑战,传统的疫情管理方式已难以应对复杂多变的防控需求。疫情数据的实时性、准确性和可追溯性成为防控工作的核心问题,亟需通过信息化手段提升管理效率。基于此背景,设计并实现一套高效、稳定的疫情管理系统具有重要的现实意义。该系统将整合疫情监测、人员管理、物资调配等核心功能,为政府部门和医疗机构提供决策支持,同时优化公众服务体验。关键词:新冠疫情、信息化管理、实时监测、决策支持、公共卫生。 本系统采用前后端分离架构,后端基于SpringBoot2框架搭建,结合MyBatis-Plus实现高效数据操作,MySQL8.0作为数据库提供稳定存储。前端使用Vue3框架开发,通过Axios实现异步通信,Element Plus组件库优化用户交互界面。系统功能涵盖疫情数据可视化、人员轨迹追踪、疫苗接种管理、物资库存预警等模块,支持多角色权限控制与数据加密传输,确保系统安全性与可扩展性。关键词:SpringBoot2、Vue3、MyBatis-Plus、MySQL8.0、数据可视化。 数据表设计 疫情动态数据表 疫情动态数据表用于存储每日疫情统计

By Ne0inhk