泛型的诗意——深入C++模板的艺术与科学(模版进阶)
前言:
在之前,小编讲述了模版的初阶内容,当时小编讲述了模版的书写,方便之后容器的讲解以及模拟实现,现在小编已经带领各位学习了很多容器,模版初阶的知识已经用的很多了,今天小编讲述一下全新的知识点,它就是模版的进阶部分,下面开始奏响模版初阶的交响曲~
正文:
1.非类型模版参量
1.1.相关的介绍
模版参数分为类型模版形参和非类型形参;其中,类型参数是指出现在模版的列表中,跟在class或者typename之类的参数类型名称,就比如下图代码的写法:
template<class T>int add(T& x,T& y);
非类型模版形参就是用一个常量作为类(函数)模版的一个参数,在类(函数)模版参数中可以将该参量当做常量来使用,如下面的使用:
template<class T,size_t N = 10> //可以给一个缺省参数给予非模版形参class Array{private:T _arr[N]; //这样的话可以定一个定长的数组};
int main()
{Array<int> s1; //可以构建一个数组长度为10的数组,也可以根据自己的兴趣来定Array<int,123> s2; //也可以根据自己的兴趣定一个长度的数组,虽然说很鸡肋,但在某一个方面还是很实用的
}
可能此时有很多读者朋友会有一点疑惑,各位可能想起之前我们在C语言阶段学习过的一个小的知识点——宏(define),宏也可以定义一个变量为一个固定的数,所以此时我们如果让N为10不可以设置一个定长的数组吗?就类似下面代码所写:
template<class T,size_t N = 10> //可以给一个缺省参数给予非模版形参class Array{private:T _arr[N]; //这样的话可以定一个定长的数组};
int main()
{Array<int> s1; //可以构建一个数组长度为10的数组,也可以根据自己的兴趣来定Array<int,123> s2; //也可以根据自己的兴趣定一个长度的数组,虽然说很鸡肋,但在某一个方面还是很实用的
}
相信很多读者朋友看到这会发现这个代码的局限性,此时我们并可以随心所欲的去设置一个定长的Array,每次生成的Array都是一个长度,可能会违背我们的初心,所以不要在产生宏就可以替代非模板形参,它俩是互相替代不了的,都在各位的领域里闪闪发亮,非模板参数可能以后在我们的讲解过程中出现的次数不会太多,不过各位读者朋友还是要知道这个知识点的,防患于未然,下面小编讲述一下它的注意事项。
1.2.注意事项
1.浮点数、类对象以及字符串不可以作为非模版参数(后两者应该截止到目前都不可以,浮点数在C++20就可以支持了)。
2.非类型的模版参数必须在编译期间就可以确认结果,也就是说我们写非类型模版参量,要不是给缺省值,要不就是显示去写,不然会报错。
2.模版的特化(本文重点)
2.1.概念
在通常情况下,使用模版可以实现一些与类型无关的代码,但对于一些特殊类型的,需要进行特殊处理,比如说:实现一个专门用来进行比较大小的函数模版:
template <class T>
bool Less(T left,T right)
{return left < right;
}
int main()
{cout << Less(1,2) << endl; //可以比较,结果是正确的。//这里我用一下之前小编实现过的时间类,具体可以看我之前的文章Date s1(2024,11,3);Date s2(2024,11,5);cout << Less(s1,s2) << endl; //可以进行比较,不过这里使用的是<运算符的重载,结果也是正确的。Date* p1 = &s1;Date* p2 = &s2;cout << Less(p1,p2) << endl; //比较之后,结果随机,因为每次我们调用构造函数,地址都是不确定的,所以此时我们进行的比较,是地址大小的比较,而不是内容的比较,所以此时我们就想在写一个函数,使得可以比较里面内容。
}
可以看到,Less在绝大多数情况下都可以正常的比较,但是在某种特殊的场景下,这个函数就不可以被使用了,在上面的代码中,p1指向的内容明显比p2的要小,但是在经过我们多次运行程序的时候,发现此时的结果就是一个随机值,有时候正确有时候错误,让人摸不着头脑,不知道为什么会有这样的结果,其实此时是涉及到了地址的开辟知识,地址的开坯都是随机的,而不是按部就班的,所以此时我们比较的是两个地址之间的大小,由于地址有随机性,自然而然的就无法到达预期结果。
不仅函数有这样的情况,有时候类也有类似的情况,所以此时,就需要对模版进行特化。即:在原有模版的基础上,针对特殊类型进行特殊化的实现方式。模版特化分类类模版特化和函数模版特化。
2.2.函数模版的特化
函数模版特化的步骤:
-
必须先有一个基础的函数模版(也就是说模版特化的前提就是要先有一个原模版,在原模版的基础上进行特化)
-
关键字template后面加一对空的<>(可能很多读者朋友感觉这个步骤很奇怪,但这就是语法要求,我们也不能怎么样)
-
函数名后跟一对尖括号,尖括号里面放置要特定特化的类型(对于这个等会在代码的例子中各位就可以感受到)
-
函数形参表:必须和模版函数的基础参数类型完全相同,如果不同编译器会报错,并且这个错误会很奇怪(也就是说我们想要特化,就得对照着原模版的参数进行特化,而不是随心所欲的乱改参数,这就不就叫做特化了)
下面小编讲述一下如何进行一个函数模版的特化,我就随便举一个例子来帮助各位去了解它的用法:
template<class T>void add(T x, T y)
{cout << "void add(T x, T y)" << endl;
}
template<>
void add<int>(int x,int y)
{cout <<"void add<int>(int x,int y)" << endl;
}
int main()
{add(1,2);add(1.1,1.2);return 0;
}
可以看出编译器在使用模板函数的时候,对于特化和原模板函数,它会优先去调用特化函数,这个就像是之前小编在模板初阶的时候,讲述如果遇到特殊的函数,我们可以不用模板化,直接在写一个现成的函数就好了,这是方法之一,现在我们又多了一个方法,那就是讲它特化,对于这两种方法的选择,小编还是认为直接再写一个函数要方便的多,因为有时候的特化真的就是可能会出错,就比如下面代码如何进行特化:
template<class T>void add(const T& x,const T& y)
{cout << "void add(const T& x,const T& y)" << endl;
}
//如果此时我们想要比较的是指针类型怎么办
很多的读者朋友遇到这个情况都可能会出错,因为此时我们在特化的时候,并不知道const到底指向哪里,这里我们要知道const修饰指针的一个规则:左值右指,const在”星号“的左边是限制的指针本身而不是它指向的值,const在“星号”的右边是限制的指针指向的内容不能改变,而不是指针本身,此时我们想要修饰的应该是x(指针本身),x的类型应该是&类型的,所以此时我们指针应该就是修饰整体,下面小编展示它的特化的写法:
template<>
void add<int*>(int * const & x,int * const& y)
{cout << "void add<int*>(int * const & x,int * const& y)" << endl;
}
这么一看,特化的时候我们很有可能出错,与其从这思索如何特化,还不如再写一个函数,这样的话出错的概率就变小了,所以在函数模版上,小编认为能写写成的就写现成的,最好不要去写特化,对于普通类型还好说,对于上述加上const类型的,有时候我们真的会分不清const究竟要修饰哪里,不害臊的说,小编到这里还对const有点疑惑,所以小编对于上述的特殊类型的写法,还是喜欢写如下现成的:
void add(int* x,int* y)
{cout <<"void add(int* x,int* y)" << endl;
}
这便就是函数模版特化的内容,其实真的学起来还是比较容易的,只不过小编还是不推荐函数进行特化,因为有时候特化太容易出错了,为了减少错误,咱们还是老老实实的去写一个现成的函数吧,出错的概率还小一点,对了,对于刚开始小编举的比较函数的例子,下面小编给出解决上述问题的两种方法:特化或者现成:
template <class T>
bool Less(T left,T right)
{return left < right;
}
//特化
template <>
bool Less<Date&>(Date* left,Date* right)
{return *left < *right;
}
//现成的
bool Less(Date* left,Date* right)
{return *left < *right;
}
2.3.类模版的特化
函数模版的特化分为两种,分别是全特化和偏特化,下面小编分别进行讲述。
2.3.1.全特化
全特化就和它的名字一样,就是把模版参数的列表全部进行特化处理,就比如下面代码所示:
template<class T1 , class T2>class wang{public:wang(){cout << "wang<T1,T2>" << endl;}private:T1 _a;T2 _b;};
template<>
class wang<int,double> //和函数模板一样,此时我们把要特化的放在类名的后面
{public:wang(){cout << "wang<int,double>" << endl;}private:int _a;double _b;
};
上面就是类模版的全特化,我们进行把类模版参数全部特殊化处理就好了,这个用法各位读者朋友要熟知,以后碰到相关的习题的时候不至于一问三不知,只不过全特化一般来说我们也是不常写的,等会小编要讲述的偏特化用处还是很大的,并且我们在把类模版给实例化以后,如果我们写的正好是全特化的,那么系统会自动调用特化的,这个就和现成和模版一个关系,全特化以后的类,其实就算不上一个真正的模板了,因为此时我们把模版参数全给定了,编译器无须自动转换了,对于现成的和需要自己制作的,编译器也是会偷懒的,所以这个点也要知道,上面函数模版的时候我忘记说了,就在这给各位讲述了吧。下面开始进入偏特化的讲解。
2.3.2.偏特化
偏特化就是任何针对模版参数进一步进行条件限制涉及的特化版本,也就是说我们特化的时候只针对部分模版参数进行特化,这时候可能有很多读者朋友会问,既然就是对部分的模版参数进行偏特化,那么为啥不叫半特化呢?其实偏特化不仅仅就是针对部分模版参数进行特化,有的时候还会堆参数的进一步限制,等会我就分两种表现方式来讲述一下偏特化,下面我们先设置好一个模板类,从而可以更好的去进行讲述:
template<class T1, class T2>class wang{public:wang(){cout << "wang<T1,T2>" << endl;}private:T1 _a;T2 _b;};
偏特化是有两种表现方式的,下面我分别讲述:
1.部分特化
部分特化就是各位读者朋友理解的,对模板参量部分进行特殊化处理,就比如下面代码所示:
template<class T1>class wang<T1,int>{public:wang(){cout << "wang<T1,int>" << endl;}private:T1 _a;int _b;};
上面就是部分特化的书写,其实还是很容易去理解的,下面我们在说说另一种表现的偏特化。
2.参数进一步的限制
偏特化还可以对参数进行进一步的限制,可以让参数便的更加有局限性,就比如下面的写法:
//对参数进行两个指针的特化
template<class T1, class T2>class wang<T1*,T2*>{public:wang(){cout << "wang<T1*,T2*>" << endl;}private:T1 _a;T2 _b;};
上面虽然模版参数还是按兵不动的,但是其实已经给他限制上了,此时我们的T1,T2变成了指针类型,这就是我们对于它进行的限制,当然不仅仅可以变成指针类型,有时候也可以是引用类型,这里小编就考验一下各位,此时如果我写的是:wang<int,double>,请问此时的T1,T2会被转换成什么,3,2,1,其实这里的T1,T2是会被转换为int和double类型,因为我们在实例化的时候,是先把T1,T2实例出来,然后再给他限制,这个特点各位读者朋友要好好地去理解。
以上便就是关于类模版特殊的知识点,各位读者朋友好好知晓偏特化的两个表现方式,不要以后仅仅知道偏特化就是对部分参量进行特化,而把对于参数进行进一步的限制给直接忘记,下面我们进入下一部分的讲述。
3.分离编译
3.1.分离编译是什么
一个程序(项目)由若干个源文件共同实现,而每一个源文件单独编译生成目标文件(obj),最后把所有目标文件链接起来形成单一的可以执行文件的过程叫做分离编译模式。小编之前写过的各种数据结构,都是这么写过来的,我一般头文件放结构体和函数的声明,源文件放定义,这就是一个简单的分离编译,一般之后我们写大型项目的时候,都会用分离编译的方式进行书写,一是显的没有那么乱,代码不会聚在一起显的冗余;二是可以更好的去各位每个人分配工作,每个人都有每个人的代码任务,这样的话效率会大大的提升,并且由减少了耦合度,增大了代码的可读性以及容易更改,但是记住一件事,模版是不可以分离编译,想要知道原因的话就继续往后进行阅读吧。
3.2.模版的分离编译
如果我们把模版声明和定义的分离的话,就会出现下面的情况:
//test.h
#include<iostream>
using namespace std;
template<class T>
void add(T x);
//test01.cpp
template<class T>
void add(T x)
{cout << x << endl;
}
//test.cpp
#include"test.h"
int main()
{add(1);return 0;
}
此时我们如果编译的时候,是不会报错的,但是当我们进行运行的时候,就会发现此时会报错误,这个错误是一个明显的链接错误,通过前面的LINK就知道是在链接的时候出错了,,可能很多读者朋友会好奇为啥子这里会进行链接错误,这就涉及到了一个编译的知识了,由于我学艺不精,于是找了个解释给各位读者朋友进行解释:
上面就是对于这个知识点的解释,各位读者朋友可以看这个图片进行了解,目前的我无法很好的进行解答,我就不各位讲述错误的知识点,下面小编给出解决模板分离编译的两种方法:
3.3.解决方法
-
把声明和定义都放在一个头文件里面。这个方法小编还是很推荐的,小编在之前对于STL里面的容器和适配器都是把声明和定义放在一个头文件的,那时候我并没有详细解释为啥这样做,这里想必各位就知道为啥这样了。
-
模板定义的位置显示实例化。这个方法不实用,小编极力不推荐。于其这样我还不如正常写个函数或者类得了。
小编在CSDN上面找到了一个二十年前一个大佬写的一篇关于分类编译的文章,各位读者朋友如果想要详情了解的话可以看看那个大佬的文章:为什么C++编译器不能支持对模板的分离式编译-CSDN博客,他写的真的很牛。
4.模板的总结
【优点】
-
模板复用了代码,节省资源,更快的迭代开发,C++标准库(STL)应运而生
-
增加了代码的灵活性
【缺点】
-
模板会导致代码膨胀问题,也会导致编译时间变长(毕竟要在编译的时候把那些模板参数转成我们想要的类型)
-
出现编译错误时,编译会非常的乱,不易定位错误。
5.总结
本文到这里也就结束了,模板进阶的知识各位一定要好好的去了解,里面的内容可能以后我们不会用到,但是在一些选择题中可能就会考到相关的问题,所以小编认为这个知识点也是很重要的,各位大佬一定要好好掌握,截至到这,小编也是完成了对于C++的初步讲述,之后的C++学习难度就要往上增了,希望我能好好的掌握吧,初阶我还有很多知识点没讲出来,希望在年前,我可以完成对于vector,list,string的模拟实现把,那么各位大佬们,我们下一篇文章见啦!
相关文章:
泛型的诗意——深入C++模板的艺术与科学(模版进阶)
前言: 在之前,小编讲述了模版的初阶内容,当时小编讲述了模版的书写,方便之后容器的讲解以及模拟实现,现在小编已经带领各位学习了很多容器,模版初阶的知识已经用的很多了,今天小编讲述一下全新的…...
【极致版】华为云Astro轻应用抽取IoTDA影子设备参数生成表格页面全流程
做份极致详细Astro调取iotda影子设备数据的操作手册,每一步都分成: 要进入哪个界面 点哪个按钮 要填什么内容(样例) 如果出错怎么办 填写示例 完全对应你这个需求:Astro轻应用抽取IoTDA影子设备数据,…...
业务中台与数据中台:企业数字化转型的核心引擎
前言:在当今数字化浪潮下,企业为了提升运营效率、加速创新步伐并更好地适应市场变化,业务中台与数据中台应运而生,成为企业架构中的关键组成部分。本文将深入探讨业务中台和数据中台的简介、发展史、技术流环节以及在实际生产中的…...
前端分页与瀑布流最佳实践笔记 - React Antd 版
前端分页与瀑布流最佳实践笔记 - React Antd 版 1. 分页与瀑布流对比 分页(Pagination)瀑布流(Infinite Scroll)展示方式按页分批加载,有明确页码控件滚动到底部时自动加载更多内容,无明显分页用户控制用…...
【网络原理】从零开始深入理解TCP的各项特性和机制.(三)
上篇介绍了网络原理传输层TCP协议的知识,本篇博客给大家带来的是网络原理剩余的内容, 总体来说,这部分内容没有上两篇文章那么重要,本篇知识有一个印象即可. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分…...
MySQL:13.用户管理
13. 用户管理 如果我们只能使用root用户,这样存在安全隐患。这时,就需要使用MySQL的用户管理。 13.1 用户 13.1.1 用户信息 MySQL中的用户,都存储在系统数据库mysql的user表中 mysql> use mysql; Database changed mysql> select h…...
leetcode0103. 二叉树的锯齿形层序遍历-medium
1 题目:二叉树的锯齿形层序遍历 官方标定难度:中 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行…...
【Go语言】ORM(对象关系映射)库
github.com/jinzhu/gorm 是 Go 语言中一个非常流行的 ORM(对象关系映射)库,用于简化与关系型数据库的交互。以下是关于它的关键信息: 核心特点 全功能 ORM 支持主流数据库:MySQL、PostgreSQL、SQLite、SQL Server 等。…...
Java : GUI
AWT 初始化界面 直接封装起来: panel 的添加 布局 流式布局,控制按钮的位置 东西南北中布局 网格布局 frame.pack();java函数,会自动选择最优的布局 事件监听 给按钮添加 添加文本 画笔 鼠标监听 键盘监听 JDialog”弹窗 默认有关闭事件 标签&#…...
ipa包安装到apple手机上
获ipa包的方式 ipatool 下载appStore的ipa包-CSDN博客 方式一:巨魔商店 原理是利用apple的漏洞,但是有低版本的系统要求 TrollStore - Always Sideload Any IPAs For FreeTrollStore - The ultimate jailbreak app for iOS. Permanently install any …...
JavaScript输出数据的方法
1. console.log() console.log()是最常用的方法之一,用于在浏览器的控制台(Console)中输出信息。这对于调试和查看变量的值非常有用。 console.log("Hello, world!");2. alert() alert()方法会弹出一个带有指定消息和确定按钮的警告…...
操作系统:计算机世界的基石与演进
一、操作系统的本质与核心功能 操作系统如同计算机系统的"总管家",在硬件与应用之间架起关键桥梁。从不同视角观察,其核心功能呈现多维价值: 硬件视角的双重使命: 硬件管理者:通过内存管理、进程调度和设…...
FFmpeg之三 录制音频并保存, API编解码从理论到实战
在学习FFmpeg的时候,想拿demo来练习,官方虽有示例,但更像是工具演示,新手不好掌握,在网上找不到有文章,能给出完整的示例和关键点的分析说明,一步一个错误,慢慢啃过来的,…...
幂等性处理解决方案实战示例
幂等性处理解决方案实战示例 幂等性是指对同一个操作执行一次或多次,产生的结果是相同的。在分布式系统、网络请求和金融交易等场景中,幂等性设计至关重要。下面我将介绍几种常见的幂等性处理方案及其实战示例。 1. 唯一标识符方案 原理:为…...
华为仓颉编程语言的实际用法与使用领域详解
华为仓颉编程语言的实际用法与使用领域详解 一、语言概述与核心特性 华为仓颉编程语言是面向万物智联时代的系统级编程语言,其核心特性包括: 三重内存安全机制:所有权系统 + 引用检查 + 硬件辅助防护零成本抽象:高级语法不牺牲底层性能全场景支持:从嵌入式设备到量子计算…...
JavaEE-多线程实战01
Java 多线程入门:第一个多线程程序 在 Java 中,多线程编程是非常重要的一部分。本篇文章将通过示例,带你快速了解如何创建第一个多线程程序,并深入分析其运行机制。 1. 创建一个线程类并继承 Thread 在 Java 中,我们…...
当AI浏览器和AI搜索替代掉传统搜索份额时,老牌的搜索引擎市场何去何从。
AI搜索与传统搜索优劣势分析 AI搜索优势 理解和处理查询方式更智能:利用自然语言处理(NLP)和机器学习技术,能够更好地理解用户的意图和上下文,处理复杂的问答、长尾问题以及多轮对话,提供更为精准和相关的…...
大模型——Spring.new快速构建AI驱动的定制化商业应用
大模型——Spring.new快速构建AI驱动的定制化商业应用 Spring.new 是一个基于人工智能的在线平台,专注于帮助营销经理和产品经理快速构建定制化工作流和小型应用。它通过自然语言输入,让用户描述需求,自动生成连接 Notion、Airtable、Slack 等工具的工作流或应用,例如将 F…...
django admin 中更新表数据 之后再将数据返回管理界面
在Django中,更新数据库中的数据并将其重新显示在Django Admin界面上通常涉及到几个步骤。这里我将详细说明如何在Django Admin中更新表数据,并确保更新后的数据能够立即在管理界面上显示。 定义模型 首先,确保你的模型(Model&…...
深度理解linux系统—— 进程概念
一、进程 进程,什么是进程? 在课本,教材中是这样描述的:程序的一个执行示例,正在执行的程序; 从内核角度来说,进程就是担当分配系统资源(CPU时间,内存)的实体…...
【如何使用solidwork编辑结构导入到simscope】
这里写自定义目录标题 欢迎使用Markdown编辑器 欢迎使用Markdown编辑器 To use Simscape Multibody Link, you must install MATLAB and the CAD applications on the same computer. To ensure the successful installation of Simscape Multibody Link, before launching yo…...
Flink 时态维度表 Join 与缓存机制实战
一、引言:为什么需要时态维度表? 在实时数仓建设中,维度表是不可或缺的一环,例如: 风控系统中,用户的风险等级在不同时间可能变化; 营销体系中,商品的促销标签会动态调整ÿ…...
Apache Tomcat 漏洞(CVE-2025-24813)导致服务器面临 RCE 风险
CVE-2025-24813Apache Tomcat 中发现了一个严重安全漏洞,标识为,该漏洞可能导致服务器面临远程代码执行 (RCE)、信息泄露和数据损坏的风险。 此缺陷影响以下版本: Apache Tomcat11.0.0-M1通过11.0.2Apache Tomcat10.1.0-M1通过10.1.34Apache Tomcat9.0.0-M1通过9.0.98了解 …...
来自B站-AI匠的“RAG的prompt设计指南“的部分截图
来自B站-AI匠的“RAG的prompt设计指南“的部分截图 0. 引言1. RAG提示词 - 部分视频截图2. 总结 - 部分视频截图3. 举例 - 部分视频截图 0. 引言 这个文章记录的是B站Up主AI匠关于RAG的prompt设计指南的视频截图。 1. RAG提示词 - 部分视频截图 笔记: Up主推荐Fa…...
【Linux】Centos7 在 Docker 上安装 Redis7.0(最新详细教程)
一、拉取 Redis 镜像 1. 从 阿里云加速器(docker hub)拉取 redis镜像,选择镜像标签为 7.2.4 docker pull redis:7.2.4 2. 准备 Redis 的配置文件(便于后期对配置文件进行修改) 3.在服务器上创建需要挂载的文件夹 mk…...
Java使用微信云服务HTTP API操作微信云开发数据库
可以直接用的工具类代码 package com.kstc.qgy.util;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.kstc.qgy.model.exception.WxException; import com.kstc.qgy.model.service.Limit; imp…...
Linux的权限
目录 1、用户分类 1.1 超级用户(root)和普通用户 1.2 普通<->超级 1.3 sudo 2、文件和目录的权限 2.1 chown&&chgrp 2.1.1 chown 2.1.2 chgrp 2.2 chmod 总结一下: 3、文件和目录的默认权限 4、共享文件 4.1 理解多用户隔离 4.2 /tmp/ 1…...
ACT游戏和MMORPG经济形态区别以及对经济循环的思考
对于原神的明日之后经济形态的不同解析 对于MMORPG游戏来说,如果采用开放市场经济的设计,以明日之后为例,系统产出端为采集、运营活动投放;玩家产出端为交易;消耗端为武器耐久的减少。但我好奇,在ACT游戏里…...
zynq7035的arm一秒钟最多可以支持触发多少次中断
一、概述 1.关于zynq7035的ARM处理器一秒能够支持多少次中断触发,需要综合来考虑。需要确定ARM处理器的参数,目前zynq7000系列,使用的双核Cortex-A9处理器。其中主频大概在500MHZ~1GHZ左右,不同的用户配置的主频可能稍微有差别。 …...
Spring MVC 拦截器教程
一、拦截器核心概念 1.1 拦截器 vs 过滤器 特性过滤器 (Filter)拦截器 (Interceptor)依赖关系Servlet容器Spring MVC框架作用范围所有Web请求Controller请求实现机制Java EE标准Java反射AOP生命周期服务器启动时初始化随Spring容器初始化功能场景字符编码、安全过滤权限校验、…...
【HPC存储性能测试】02-ior带宽性能测试
文章目录 一、前言二、软件安装1、安装依赖2、安装软件 三、参数说明1、mpirun参数2、ior参数 四、测试说明 一、前言 ior introduction | github hpc ior IOR 测试工具使用 POSIX、 MPIIO 或 HDF5接口对并行文件系统进行基准测试 通常使用IOR测试工具时,一般会配合…...
【RabbitMQ】保证消息不丢失
要确保 RabbitMQ 在消费者(Python 服务)重启或挂掉时消息不丢失,需结合 消息持久化、确认机制(ACK) 和 死信队列(DLX) 实现高可靠性: 1. 消息持久化(Durabilityÿ…...
算法效率的钥匙:从大O看复杂度计算 —— C语言数据结构第一讲
目录 1.数据结构与算法 1.1数据结构介绍 1.2算法介绍 2.算法效率 2.1复杂度 2.1.1时间复杂度 2.1.1.1时间复杂度计算示例1 2.1.1.2时间复杂度计算示例2 2.1.1.3时间复杂度计算示例3 2.1.1.4时间复杂度计算示例4 2.1.1.5时间复杂度计算示例5 2.1.1.6时间复杂度计算示例6…...
AI赋能守护行车安全新防线,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建驾驶车辆场景下驾驶员疲劳分心驾驶行为智能检测预警系统
在当今社会,随着科技生产力的飞速发展,汽车早已成为人们日常出行不可或缺的交通工具。它不仅极大地提高了人们的出行效率,也为生活带来了诸多便利。然而,随着汽车保有量的不断增加,交通安全问题也日益凸显。疲劳驾驶和…...
HNUST湖南科技大学-嵌入式考试选择题题库(109道纠正详解版)
HNUST嵌入式选择题题库 1.下面哪点不是嵌入式操作系统的特点。(B) A.内核精简 B.功能强大 C.专用性强 D.高实时性 解析: 嵌入式操作系统特点是内核精简、专用性强、高实时性,而"功能强大"通常指的是通用操作系统&#x…...
【音视频】SDL事件
SDL 事件 函数 SDL_WaitEvent(): 等待一个事件SDL_PushEvent(): 发送一个事件SDL_PumpEvents(): 将硬件设备产生的事件放入事件队列,用于读取事件,在调用该函数之前,必须调用SDL_PumpEvents搜集键盘等事件…...
[特殊字符]实战:使用 Canal + MQ + ES + Redis + XXL-Job 打造高性能地理抢单系统
📚目录 项目背景 技术栈总览 详细流程分析 3.1 Canal监听MySQL Binlog 3.2 MQ中转传递订单变化 3.3 Elasticsearch存储并查询附近订单 3.4 Redis高性能抢单Lua防止抢单冲突 3.5 XXL-Job定时任务处理 完整系统流程图 总结 一、项目背景 针对类似外卖、跑…...
FPGA基础之基础语法
一、基本模块结构 Verilog 代码以 模块(Module) 为单位,每个模块对应一个硬件功能单元(如逻辑门、寄存器等)。 基本格式: module 模块名 (// 输入输出端口声明input 端口1,input 端口2,output 端口3 );…...
影楼精修-皮肤瑕疵祛除算法解析
注意:本文样例图片为了避免侵权,均使用AIGC生成; 顾名思义,皮肤瑕疵祛除旨在祛除人像照片皮肤区域的痘痘/斑点/痣/胎记等瑕疵;当前主流算法方案可分为传统图像处理方法和基于深度学习的方法,本文重点介绍基…...
2025蓝桥杯省赛网络安全组wp
文章目录 黑客密室逃脱ezEvtxflowzipEnigma星际xml解析器EBC-TrainAES-CBC 黑客密室逃脱 提示猜文件名,猜几个常见的,app.py读到源码 这里也是脑抽了一下,把密钥看成1236了。。。卡了五分钟左右,解出来的时候已经降到300多分了&a…...
【数据结构】·励志大厂版(复习+刷题):二叉树
前引:哈喽小伙伴们!经过几个月的间隔,还是逃脱不了再次复习的命运!!!本篇文章没有冗杂的闲话,全是干货教学,带你横扫二叉树的几种遍历,怎么前序、、中序、后续࿱…...
Spark-Streaming2
一.有状态转化操作 1. UpdateStateByKey UpdateStateByKey 原语用于记录历史记录,有时,我们需要在 DStream 中跨批次维护状态(例如流计算中累加 wordcount)。针对这种情况,updateStateByKey()为我们提供了对一个状态变量的访问&…...
《深入浅出Git:从版本控制原理到高效协作实战》
Git的原理和使用 1、Git初识与安装2、Git基本操作2.1、创建Git本地仓库2.2、配置Git2.3、认识工作区、暂存区、版本库2.4、修改文件2.5、版本回退2.6、撤销修改2.7、删除文件 3、Git分支管理3.1、理解分支3.2、创建、切换、合并分支3.3、删除分支3.4、合并冲突3.5、合并模式3.6…...
内耗型选手如何能做到不内耗?
以下是针对「内耗型选手」的系统性解决方案,结合认知神经科学、行为心理学和效能管理理论,提供可落地的策略框架: 一、建立「内耗熵值」监测系统 1. 绘制内耗热力图 用时间轴记录每日内耗触发点: 时间段内耗场景能量损耗值&…...
pyspark将hive数据写入Excel文件中
不多解释直接上代码,少python包的自己直接下载 #!/usr/bin/env python # -*- encoding: utf-8 -*- from pyspark.sql import SparkSession import pandas as pd import os# 初始化 SparkSession 并启用 Hive 支持 spark SparkSession.builder \.appName("sel…...
Java大师成长计划之第5天:Java中的集合框架
📢 友情提示: 本文由银河易创AI(https://ai.eaigx.com)平台gpt-4o-mini模型辅助创作完成,旨在提供灵感参考与技术分享,文中关键数据、代码与结论建议通过官方渠道验证。 在 Java 编程中,集合框架…...
rt-linux下的D状态的堆栈抓取及TASK_RTLOCK_WAIT状态
一、背景 在之前的博客 缺页异常导致的iowait打印出相关文件的绝对路径-CSDN博客 里的 2.1 一节里的代码,我们已经有了一个比较强大的抓取D状态和等IO状态超过阈值的waker和wakee的堆栈状态的内核模块。在之前的博客 增加等IO状态的唤醒堆栈打印及缺页异常导致iowa…...
数据结构【堆和链式结构】
堆和链式结构 1.堆的概念和定义1.1堆1.2二叉树的性质 2.堆的实现3.实现链式二叉树3.1链式二叉树的概念3.2前中后遍历3.3遍历(举例) 1.堆的概念和定义 1.1堆 定义:是特殊的二叉树 #mermaid-svg-vWPNPMGSLe0nGNcd {font-family:"trebuch…...
聊一聊自动化测试
目录 一、自动化测试的定义与核心价值 (一)什么是自动化测试 (二)核心价值:从人工到智能的跨越 二、自动化测试的发展阶段 (一)萌芽阶段(早期) (二&…...
vue2 开发一个实习管理系统电脑端-前端静态网站练习
为了快速的掌握vue2的所学习到的知识点,最近又使用vue2和element-ui 做了一个实习管理系统来巩固自己的前端技术,我觉得对于新手来说,多写代码,多找一些项目练习,是提供自己编程能力的一个很好的办法,这也是…...