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

人工智能:深度学习模型的优化策略与实战调参

人工智能:深度学习模型的优化策略与实战调参

人工智能:深度学习模型的优化策略与实战调参 💡 学习目标:掌握深度学习模型的核心优化方法,理解调参的底层逻辑,能够独立完成模型从欠拟合到高性能的调优过程。 💡 学习重点:正则化技术的应用、优化器的选择与参数调整、批量大小与学习率的匹配策略。 48.1 模型优化的核心目标与常见问题 在深度学习项目中,我们训练的模型往往会出现欠拟合或过拟合两种问题。优化的核心目标就是让模型在训练集和测试集上都能达到理想的性能,实现泛化能力的最大化。 ⚠️ 注意:模型优化不是一次性操作,而是一个“诊断-调整-验证”的循环过程,需要结合数据特性和任务需求逐步迭代。 48.1.1 欠拟合的识别与特征 欠拟合是指模型无法捕捉数据中的潜在规律,表现为训练集和测试集的准确率都偏低。 出现欠拟合的常见原因有以下3点: 1. 模型结构过于简单,无法拟合复杂的数据分布。 2. 训练数据量不足,或者数据特征维度太低。 3. 训练轮次不够,模型还未充分学习到数据的特征。 48.1.2 过拟合的识别与特征 过拟合是指模型在训练集上表现极好,但在测试集上性能大幅下降。 出现过拟合的常见原因有以下3点:

By Ne0inhk
爆火AI圈的OpenClaw(小龙虾):能干活的本地AI智能体,一文吃透入门到实战

爆火AI圈的OpenClaw(小龙虾):能干活的本地AI智能体,一文吃透入门到实战

🔥个人主页:Cx330🌸 ❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》 《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔 《Git深度解析》:版本管理实战全解 🌟心向往之行必能至 🎥Cx330🌸的简介: 目录 前言: 一、先搞懂:OpenClaw到底是什么?为什么这么火? 1.1 项目核心定位 1.2 爆火的核心原因:踩中AI落地痛点 1.3 OpenClaw vs 传统AI vs 自动化工具 二、OpenClaw核心架构:它是怎么干活的? 三、保姆级部署:全平台一键安装,小白也能搞定 3.1 部署前置准备 3.2 官方一键脚本(新手首选,

By Ne0inhk
终极指南:全面精通 Docker 在 Ubuntu、CentOS 及 Windows 上的安装与实战配置

终极指南:全面精通 Docker 在 Ubuntu、CentOS 及 Windows 上的安装与实战配置

在当今飞速发展的软件开发与运维(DevOps)领域,Docker 已然成为一项不可或缺的革命性技术。它通过“容器化”这一轻量级的虚拟化方案,将应用程序及其所有依赖项打包到一个可移植的容器中,从而确保了从开发、测试到生产环境的高度一致性与可靠性。无论您是初涉容器世界的开发者,还是寻求标准化部署流程的运维工程师,掌握 Docker 的安装与配置都是您的必修课。 本指南将以前所未有的深度,为您提供一份跨越三大主流操作系统——Ubuntu、CentOS 和 Windows——的 Docker 安装与高级配置的终极手册。我们将不仅仅是罗列命令,而是深入剖析每一步操作背后的原理,解读每一个配置项的意义,并结合源文件中的高清截图,为您带来身临其境的学习体验,确保您在读完本文后,能够充满自信地驾驭 Docker 的安装与维护。 第一章:Ubuntu 环境下的 Docker 之旅——从零到精通 Ubuntu,作为广受欢迎的 Linux 发行版,是运行 Docker 的理想平台。我们将从环境检查开始,一步步完成 Docker

By Ne0inhk
手把手教你:在 Windows 部署 OpenAkita 并接入飞书模块,实现真正能干活的本地 AI 助手

手把手教你:在 Windows 部署 OpenAkita 并接入飞书模块,实现真正能干活的本地 AI 助手

目 录 * 前言 * 第一章:为什么选 OpenAkita,而不是直接用 OpenClaw? * 1.1 当前 AI 助理的几个现实痛点 * 1.2 OpenAkita 的核心优势(对比 OpenClaw) * 1.3 谁最适合用 OpenAkita? * 第二章:Windows 下安装 OpenAkita(两种方案) * 2.1 准备工作 * 2.2 方案一:一键脚本安装(适合能接受 PowerShell 的用户) * 2.3 方案二:桌面安装包(最像普通软件,新手友好) * 第三章:配置蓝耘(Lanyun)平台 API 密钥

By Ne0inhk