【C++】模板进阶
文章目录
- 一、非类型模板参数
- 1、非类型模板参数
- 2、C++11 中的 array 类
- 二、模板的特化
- 1、模板特化的概念
- 2、函数模板特化
- 3、类模板特化
- 3.1 全特化
- 3.2 偏特化
- 三、模板的分离编译
- 四、模板总结
一、非类型模板参数
1、非类型模板参数
模板参数分为类型形参与非类型形参,类型形参即出现在模板参数列表中,跟在 class 或者 typename 关键字之后的参数类型名称,我们前面使用的所有模板参数都是类型形参;而非类型形参则是用一个常量作为类模板/函数模板的一个参数,在类模板/函数模板中可将该参数当成常量来使用。
我们以静态数组为例;在没有非类型模板参数时,我们采用如下方式来定义一个静态数组:
#define N 10
template<class T>
class arr {
public://...
private:T _a[N];
};void test1() {arr<int> arr;
}
但是这样有一个缺陷,因为 N 的大小是固定的,所以我们只能定义出 N 个元素大小的 arr对象,那么此时如果我们想要同时定义两个大小为 10 和 100 的数组显然是做不到的。
C++ 中设计了非类型模板参数来解决了这个问题,如下,我们可以通过传递不同的非类型形参来定义不同的类,非类型模板参数在函数模板中的使用也是如此:
template<class T, size_t N>
class arr {
public://...
private:T _a[N];
};void test1() {arr<int, 10> arr1;arr<double, 100> arr2;
}
注意事项:
- 非类型模板参数也可以给定缺省值;
- 非类型模板参数只适用于整形,不适用于浮点数、类对象以及字符串;
- 非类型的模板参数必须在编译期间就能确认结果,即非类型模板参数的实参只能是常量。
2、C++11 中的 array 类
C++ 11 中引入了一个新类 – array,array 使用非类型形参作为模板参数,其底层其实就相当于静态数组:
由于 array 底层是静态数组,所以 array 的特性和静态数组的特性一样 – 数据存放在栈上、不要求数据连续存储 (使用 [] 给指定位置的数据赋值)、也不允许 push_back (不能扩容):array 使用文档
有的同学可能有疑问 – 既然 array 的底层就是静态数组,那为什么不直接使用C语言中的静态数组,而要将它封装成为一个新类呢?答案是为了更严格的进行越界检查。
C语言静态数组对越界的检查规则是 – 越界读不检查、越界写抽查:
而 array 里面重载了 [] 运算符,在 operator[]() 函数里面对数组边界进行了判断,所以不管是越界读还是越界写都会检查出来:
所以,其实 C++ 11 设计出 array 类是为了让 array 替代掉C语言的静态数组,以此来帮助人们更早的发现并解决程序中可能出现的越界问题,但是由于人们数组已经用习惯了,所以 array 其实被使用的并不多。
注:array 除了具有安全性,还有可读性、抽象性、兼容性等优点。
二、模板的特化
1、模板特化的概念
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理;比如,实现了一个专门用来进行小于比较的函数模板:
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{return left < right;
}void test4()
{cout << Less(1, 2) << endl; // 可以比较,结果正确Date d1(2022, 7, 7);Date d2(2022, 7, 8);cout << Less(d1, d2) << endl; // 可以比较,结果正确Date* p1 = &d1;Date* p2 = &d2;cout << Less(p1, p2) << endl; // 可以比较,结果错误
}
可以看到,Less 绝对多数情况下都可以正常比较,但是在特殊场景下就得到错误的结果;上述示例中,p1 指向的 d1 显然小于 p2 指向的d2 对象,但是 Less 内部并没有比较 p1 和 p2 指向的对象内容,而比较的是 p1 和 p2 指针的地址,这就无法达到预期而发生错误。
此时,就需要对模板进行特化 – 即在原模板类的基础上,针对特殊类型进行特殊化的处理;模板特化中分为函数模板特化与类模板特化。
2、函数模板特化
函数模板特化的步骤如下:
- 必须要先有一个基础的函数模板;
- 关键字 template 后面接一对空的尖括号<>;
- 函数名后跟一对尖括号,尖括号中指定需要特化的类型;
- 函数形参表必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
如下:
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{return left < right;
}//对Date*类型进行模板特化
template<>
bool Less<Date*>(Date* left, Date* right)
{return *left < *right; //特殊处理:比较left和right指向的内容,而不是left和right本身
}
有的同学可能会说,我直接重载一个参数类型为 Date* 的函数即可,为什么要费这么大劲搞成模板的特化呢?-- 确实,由于函数支持重载,所以我们完全可以将重载一个/多个特殊类型的形参;所以,一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出 (函数重载)。
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{return left < right;
}//Date*类型的函数重载
bool Less(Date* left, Date* right)
{return *left < *right; //特殊处理:比较left和right指向的内容,而不是left和right本身
}
如上,对于一些参数类型复杂的函数模板直接给出,即实现为函数重载,这种方法该种实现简单明了,代码的可读性高,容易书写,因此函数模板不建议特化。
3、类模板特化
类模板特化又分为全特化与偏特化。
3.1 全特化
全特化即是将模板参数列表中所有的参数都确定化,如下:
template<class T1, class T2>
class Data {
public:Data() { cout << "Data<T1, T2>" << endl; }
private:T1 _d1;T2 _d2;
};template<>
class Data<int, char> { //类模板全特化
public:Data() { cout << "Data<int, char>" << endl; }
private:int _d1;char _d2;
};
3.2 偏特化
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本。偏特化有以下两种表现方式:
- 部分特化 – 将模板参数类表中的一部分参数特化;
- 参数更进一步的限制 – 偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。
我们以如下类模板为例:
template<class T1, class T2>
class Data {
public:Data() { cout << "Data<T1, T2>" << endl; }
private:T1 _d1;T2 _d2;
};
部分特化:
//部分特化--将第二个参数特化为int
template <class T1>
class Data<T1, int> {
public:Data() { cout << "Data<T1, int>" << endl; }
private:T1 _d1;int _d2;
};void test6() {Data<int, char> d1; //使用普通模板实例化Data<int, int> d2; //第二个参数与模板特化中的特化参数相同,优先使用特化模板进行实例化
}
可以看到,我们可以将模板中的部分参数显示指定为某种具体类型,这样模板参数在进行匹配时会优先匹配。
参数更进一步限制:
//参数更进一步限制--两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*> {
public:Data() { cout << "Data<T1*, T2*>" << endl; }
private:T1 _d1;T2 _d2;
};//两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data <T1&, T2&> {
public:Data(const T1& d1, const T2& d2): _d1(d1), _d2(d2){cout << "Data<T1&, T2&>" << endl;}
private:const T1& _d1;const T2& _d2;
};void test7() {Data<double, int> d1; // 调用特化的int版本Data<int, double> d2; // 调用基础的模板Data<int*, int*> d3; // 调用特化的指针版本Data<int&, int&> d4(1, 2); // 调用特化的指针版本
}
可以看到,我们可以通过偏特化对模板参数进行进一步的限制,比如模板参数定义为 <T*, T*>,这样只要实参为指针类型,不管是 int*、double*、还是 vector<int>*,都会调用此特化模板;又比如将模板参数定义为为 <T&, T&>,这样只要实参是引用类型就会调用此特化模板;
从而实现了在限制参数类型的同时又不会将参数局限为某一种具体类型。
三、模板的分离编译
阅读我博客的同学会发现,自从学习了模板以后,凡是要用到模板的类我们成员函数的声明和定义都是放在一起的,或者是直接在类中给出函数的定义,而不提供函数的声明,比如我们模拟实现的 vector、list、stack、queue、priority_queue 等容器;
那为什么我们不像C语言或者非模板类那样将类成员函数的声明和定义进行分离呢?函数声明和定义分离不是即能够方便别人阅读我们的代码,还能够保护源码不被泄露吗?-- 这是因为模板不支持分离编译。
我们以简易版的 stack 为例:
//Stack.h
#include<iostream>
using namespace std;template<class T>
class Stack
{
public:Stack(int capacity);~Stack();void push(const T& x);private:T* _a;int _top;int _capacity;
};
//Stack.cpp
#include "stack.h"template<class T>
Stack<T>::Stack(int capacity)
{cout << "Stack(int capacity = )" << capacity << endl;_a = (T*)malloc(sizeof(T) * capacity);if (_a == nullptr){perror("malloc fail");exit(-1);}_top = 0;_capacity = capacity;
}template<class T>
Stack<T>::~Stack()
{cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;
}template<class T>
void Stack<T>::push(const T& x)
{// ....//_a[_top++] = x;
}
如上,我们将模板类 stack 进行声明和定义分离,注意:
1、类模板的外部成员定义不得具有默认参数,即类模板声明与定义分离时不能成员函数不能使用缺省参数;
2、类模板的成员函数在分离定义时必须指明该函数是属于那个类的,而 stack 是类名,stack<T> 才是类型,所以我们需要在每个成员函数前面指明类类型 stack<T>。
但是当我们编译运行的时候我们发现分离定义的所有成员函数都出现了链接性错误:
造成这种错误的原因如下:
在C语言 程序环境和预处理 那一节我们学习了一个 .c/.cpp 程序要变成 .exe 可执行程序一共要经历四个步骤,分别是预处理、编译、汇编和链接,这期间它们的工作分别为:
- 预处理:注释的删除,#define 定义的符号、宏的替换以及删除,各种条件编译的处理,头文件的展开;
- 编译:进行语法分析、词法分析、语义分析和符号汇总;
- 汇编:生成符号表;
- 链接:合并段表、符号表的合并和重定位。
同时,预处理、编译、汇编这几个阶段每个源文件 (.c 文件) 都是独立进行的,只有在链接时才会将这几个目标文件合并到一起形成可执行程序。
在了解了这些知识以后,我们就可以得出程序报错的原因了:
1、预处理时,Stack.h 头文件分别展开到 Stack.cpp 和 Test.cpp 源文件中;
2、经过编译,Stack.cpp 和 Test.cpp 分别转变成汇编代码;
3、在汇编时,由于 Test.cpp 里面只有 Stack、~Stack、push 等函数的声明,而没有其定义,所以 Test.cpp 生成的符号表会给这些函数对应一个无效地址;同时,由于 Stack.cpp 里面并没有对模板实例化的代码,即没有 Stack<int>,也就没有生成具体的代码,所以 Stack.cpp 的符号表里面函数对应的也是无效地址;
4、在链接时,需要将 Test.cpp 和 Stack.cpp 符号表中的内容进行合并与重定位,但是由于它们符号表中的都是无效地址,所以发生链接错误。
在找出错误原因后有的同学可能会说,这简单,在 Stack.cpp 中对模板进行显式实例化即可,如下:
//Stack.cpp 中增加显式实例化的代码
template
class Stack<int>;
这样做确实可以,但是如果我们此时还要定义一个 double 类型的对象呢?那么我们又需要将 Stack.cpp 中的显式实例化类型改为 double,也就是说,在同一份代码中我们只能定义同一种类型的对象,那么这样也就失去了模板原本的意义了。
所以,模板不支持分离编译,我们一般采用其他的解决办法,如下:
1、模板函数不进行声明,直接在类里面给出函数的定义;(如果类很大时这种方法不方便别人阅读我们的代码,不推荐使用;当类较小时可以这样做,比如我们之前模拟实现的 STL 容器)
2、将模板函数的声明和定义放到同一个文件 “xxx.hpp” 中 (hpp:.h + .cpp) 。(这种方式使用于类较大时,方便别人快速了解我们的类)
3、注:这两种方法都有一个缺点 – 会暴露源码,因为函数的声明和定义是在一个文件中的,我们将类提供给别人使用时不得不将源码也暴露给别人,这也是模板的一个缺点。
四、模板总结
模板的优点:
- 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库 (STL) 因此而产生;
- 模板增强了代码的灵活性。
模板的缺点:
- 模板会导致代码膨胀问题,也会导致编译时间变长;
- 出现模板编译错误时,错误信息非常凌乱,不易定位错误;
相关文章:
【C++】模板进阶
文章目录一、非类型模板参数1、非类型模板参数2、C11 中的 array 类二、模板的特化1、模板特化的概念2、函数模板特化3、类模板特化3.1 全特化3.2 偏特化三、模板的分离编译四、模板总结一、非类型模板参数 1、非类型模板参数 模板参数分为类型形参与非类型形参,类…...
三板斧解决leetcode的链表题
在《波奇学单链表》中我们提到单链表的两个特点单向性。头节点尾节点的特殊性导致分类讨论的情况。如何看单链表?让我们简化成下图cur表示当前节点,下图表示cur移动,圆圈表示值用哨兵卫节点(新的头节点)和把尾节点看成NULL来把头尾节点一般化…...
全生命周期的云原生安全框架
本博客地址:https://security.blog.csdn.net/article/details/129423036 一、全生命周期的云原生安全框架 如图所示: 二、框架说明 在上图中,我们从两个维度描述各个安全机制,横轴是开发和运营阶段,细分为编码、测试…...
【本地网站上线】ubuntu搭建web站点,并内网穿透发布公网访问
【本地网站上线】ubuntu搭建web站点,并内网穿透发布公网访问前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名4.3 测试访问公网固定二级子…...
电脑怎么重装系统?教你轻松掌握这些方法
重新安装计算机系统有两种原因:一种是计算机系统可以正常使用,但是电脑比较卡,为了提高它的运行速度,所以想要通过重新安装系统来解决这个问题;另一种原因是计算机系统文件丢失,系统出现蓝屏,或者黑屏的情况…...
leetcode-每日一题-2379(简单,字符串)
久违的简单题......给你一个长度为 n 下标从 0 开始的字符串 blocks ,blocks[i] 要么是 W 要么是 B ,表示第 i 块的颜色。字符 W 和 B 分别表示白色和黑色。给你一个整数 k ,表示想要 连续 黑色块的数目。每一次操作中,你可以选择…...
SLF4J日志框架在项目中使用
介绍 SLF4J全称“Simple Logging Facade for Java”,作为各种日志框架的简单门面。例如: java.util.logging、logback 、 reload4j等。只需要切换日志框架的jar包依赖就可以切换日志框架。 SLF4J支持的日志框架包含如下: log4j:…...
Spark MLlib 模型训练
Spark MLlib 模型训练决策树随机森林GBDTSpark MLlib 开发框架下 : 监督学习 : 回归 (Regression) , 分类 (Classification) , 协同过滤 (Collaborative Filtering)非监督学习 : 聚类 (Clustering) 、频繁项集 (Frequency Patterns) 例子分类 : 算法分类 : 算法分类算法子分类…...
Python中变量的作用域精讲
文章目录前言一、局部变量二、全局变量前言 变量的作用域是指程序代码能够访问该变量的区域,如果超出该区域,再访问时就会出现错误。在程序中,一般会根据变量的 “有效范围” 将变量分为 “全局变量” 和 “局部变量”。 一、局部变量 局部变…...
数据仓库工程师的工作职责的相关介绍
1. BI 开发工程师的工作内容是什么? BI开发工程师(Business Intelligence Developer)是负责设计和开发企业级BI系统的专业人员。他们的主要工作是从多个数据源中提取、转换、加载和分析数据,以支持企业决策。以下是BI开发工程师的…...
ESP UART 介绍
1 UART 介绍 UART 是一种以字符为导向的通用数据链,可以实现设备间的通信。异步传输的意思是不需要在发送数据上添加时钟信息。这也要求发送端和接收端的速率、停止位、奇偶校验位等都要相同,通信才能成功。 1.1 UART 通信协议 一个典型的 UART 帧开始…...
第十三届蓝桥杯省赛Python大学B组复盘
目录 一、试题B:寻找整数 1、题目描述 2、我的想法 3、官方题解 4、另解 二、试题E:蜂巢 1、题目描述 2、我的想法 3、官方题解 三、试题F:消除游戏 1、题目描述 2、我的想法(AC掉58.3%,剩下全超时&#x…...
linux入门---vim的配置
这里写目录标题预备知识如何配置vimvim一键配置预备知识 在配置vim之前大家首先得知道一件事就是vim的配置是一人一份的,每个用户配置的vim都是自己的vim,不会影响到其他人,比如说用户xbb配置的vim是不会影响到用户wj的,虽然不同…...
Python简写操作(for、if简写、匿名函数)
Python简写操作(for、if简写、匿名函数)1. for 简写1.1 一层 for 循环1.2 两层 for 循环2. if 简写3. for 与 if 的结合简写4. 匿名函数 lambda1. for 简写 举个例子: y [1, 2, 3, 4, 5, 6] result [(i * 2) for i in y] print(result)# …...
毕业设计常用模块之温湿度模块DHT11模块使用
DHT11是一款可以测量温度数据和湿度数据的传感器 产品特点 暖通空调、除湿器、农业、冷链仓储、测试及检测设备、消费品、汽车、自动控制、数据记录器、气 象站、家电、湿度调节器、医疗、其他相关湿度检测控制 外形尺寸 第3管脚:NC 是没有用的 典型电路 通信方式…...
Cadence Allegro 导出Design Rules Net Shorts Check(DRC)Report报告详解
⏪《上一篇》 🏡《上级目录》 ⏩《下一篇》 目录 1,概述2,Design Rules Net Shorts Check(DRC)Report作用3,Design Rules Net Shorts Check(DRC)Report示例4,Design Rules Net Shorts Check(DRC)Report导出方法4.1,方法14.2,方法2...
第 46 届世界技能大赛浙江省选拔赛“网络安全“项目C模块任务书
第46届世界技能大赛浙江省选拔赛"网络安全"项目C模块(夺旗行动(CTF)挑战)第46届世界技能大赛浙江省选拔赛"网络安全"项目C模块第一部分 WEB第二部分 CRYPTO第三部分 REVERSE第四部分 MISC第五部分 PWN第46届世…...
C++:详解C++11 线程(一):MingGW 各版本区别及安装说明
MingGW 各版本区别一:MinGW、MinGW-w64 简介二:MinGW 各版本参数说明三:下载解压一:MinGW、MinGW-w64 简介 MinGW(全称为 Minimalist GNU for Windows),它实际上是将经典的开源 C 语言编译器 G…...
第十二章 ArrayList和 LinkedList的区别
ArrayList:基于动态数组(自动扩容),连续内存存储,由于底层是数组,适合使用下标进行访问,但扩容一直都是数组的缺点,所以使用尾插法进行扩容可以有效提高扩容效率。还有就是创建Array…...
案例06-复用思想的接口和SQL
目录 一:背景介绍 二:思路&方案 三:过程 1.Controller层接口的复用 2.Mapper层sql语句的复用 四:总结 一:背景介绍 我们在开发项目的过程中非常容易出现的一种现象就是用什么我就直接写什么,就像我…...
【Java学习笔记】17.Java 日期时间(2)
前言 本章继续介绍Java的日期时间。 Calendar类 我们现在已经能够格式化并创建一个日期对象了,但是我们如何才能设置和获取日期数据的特定部分呢,比如说小时,日,或者分钟? 我们又如何在日期的这些部分加上或者减去值呢? 答案…...
【学习Docker(八)】Docker Canal的安装与卸载
座右铭:《坚持有效输出,创造价值无限》 最近想了解下canal,自行搭建并完成数据同步。经过了几天的踩坑之旅,今天终于搭建成功了。 环境:canalv1.1.5、MySQL8.0、JDK1.8 安装MySQL 创建存放目录 mkdir /docker-localm…...
python的django框架从入门到熟练【保姆式教学】第三篇
在前两篇博客中,我们介绍了Django框架的模型层和数据库迁移功能。本篇博客将重点介绍Django的视图层(View),并讲解如何创建视图函数和URL路由。 视图层(View) Django的视图层是Django应用程序的另一个核心…...
Open3D(C++) Ransac拟合球体(详细过程版)
目录 一、算法原理1、计算流程2、参考文献二、代码实现三、结果展示一、算法原理 1、计算流程 空间球方程: ( x − a ) 2 + ( y − b...
Antlr Tool与antlr runtime的版本一致性问题
1. 意外的问题 在学习Antlr4的visitor模式时,使用IDEA的Antlr插件完成了Hello.g4文件的编译,指定的package为com.sunrise.hello 使用visitor模式遍历语法解析树,遍历过程中打印hello语句 public class HelloVisitorImpl extends HelloBaseVi…...
嵌入式中CAN测试自动化方法分析
can的基础知识 CAN是什么? CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO*1 国际标准化的串行通信协议在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类…...
基于c++、opencv、cuda、Visual Studio编程
一、前言 opencv自带的支持的cuda的函数不少,但是不一定够用,而且已经支持的函数有些还不是十分的完善。所以更多的时候还需要编写自己的kernel以进行加速自定义处理。如果基于opencv进行计算机视觉相关开发工作,那么熟悉c++、opencv、cuda编程是避免不了的环节。 二、准备工…...
MATLAB——DFT(离散傅里叶变换)
题目1: 已知有限长序列x(n)为: x(n)[0,1,2,3,4,5,6,7,8,9],求x(n)的DFT和IDFT。要求 1)画出序列傅里叶变换对应的|X(k)|和arg[X(k)]图形。 2)画出原信号与傅里叶逆变换IDFT[X(k)]图形进行比较。 知识点: DF…...
高端Zynq ultrascale+使用GTH回环测试 提供2套工程源码和技术支持
这目录1、前言2、GTH 高速收发器介绍GTH 高速收发器结构参考时钟的选择和分配GTH 发送端GTH 接收端3、vivado工程详解4、上板调试验证5、福利:工程代码的获取1、前言 Xilinx系列FPGA内置高速串行收发器,配有可配置的IP方便用户调用,按照速度…...
入门(Createing a scene)
这一部分将对three.js来做一个简要的介绍 首先将开始搭建一个场景,其中包含一个正在旋转的立方体 梦开始的地方 在开始使用threeJS之前,我们需要创建一个HTML文件来显示它(将下列HTML代码保存为你电脑上的一个HTML文件然后在你的浏览器中打…...
Unity入门精要03---透明效果
本节知识架构 1.渲染顺序与渲染队列 如果采用了透明度混合即要是实现半透明效果,那么就要关闭深度写入,那么此时渲染顺序就会变得非常非常重要,不然会出现不正确的遮挡效果。具体的分析可见书中解释 一句话概括就是因为没有写入深度…...
一文解码:如何在人工智能热潮下实现产业“智”变
近期由ChatGPT有关人工智能的话题引发了全民热议,在这股子浪潮下,讨论最多的话题就是ChatGPT的出现会为我们带来怎样的技术变革?是否会改变我们目前的生产方式?对于未来人工智能技术的发展,我们该如何客观看待…...
webshell管理工具-菜刀的管理操作
什么是webshell Webshell是一种运行在Web服务器上的脚本程序,通常由黑客使用来绕过服务器安全措施和获取对受攻击服务器的控制权。Webshell通常是通过利用Web应用程序中的漏洞或者弱密码等安全问题而被植入到服务器上的。 一旦Webshell被植入到服务器上࿰…...
dl----算法常识100例
1.depthwise卷积&&Pointwise卷积 depthwise与pointwise卷积又被称为Depthwise Separable Convolution,与常规卷积不同的是此卷积极大地减少了参数数量,同时保持了模型地精度,depthwise操作是先进行二维平面上地操作,然后利…...
京东百亿补贴,不要把方向搞偏了
出品 | 何玺 排版 | 叶媛 我吐槽来了。 3月6日0时,京东正式加入百亿补贴战局。那么,京东百亿补贴力度如何?用户又有什么反馈?我们一起来看看。 01 京东百亿补贴实测 京东百亿补贴上线的第一天,玺哥就亲自进行了体…...
Java中的static与final关键字
一、static关键字 static修饰位置表示含义变量表示这是一个类变量,类加载时分配在堆中方法静态方法,不依赖于对象可直接通过类标识访问代码块静态代码块,只在类加载初始化阶段时执行一次内部类静态嵌套类,表示只是放在外部类的文…...
开学新装备 - 学生党是否该入手 MacBook
学生党是否该入手 macbook 这个问题,相信许多人在许多社区都有看到过类似讨论。只不过,许多讨论都掺杂了信仰、智商税、不懂、不熟悉未来需求等各种因素,导致内容空洞价值不大。这篇文章,抛开了所有非理性因素,详细的告…...
【前端技巧】ESLint忽略检查行和文件
Author:Outman Date:2023-03-10 ESLint忽略检查行和文件 一、注释方式 1.注释忽略 —— 块注释 /* eslint-disable */ console.log(test); /* eslint-enable */2.注释忽略 —— 忽略指定规则项 /* eslint-disable no-alert, no-console */ alert(tes…...
单片机学习笔记之点阵(8x8)
心血来潮,想捡一下丢了很久的单片机,纪录一下单片机学习简单的点阵显示,及踩到的䟘,找到吃灰很久的普中科技开发板(非广告,为毕设学习买的)。 1. 使用工具 使用开发板: 普中科技开发…...
我一个普通程序员,光靠GitHub打赏就年入70万,
一个国外程序员名叫 Caleb Porzio在网上公开了自己用GitHub打赏年入70万的消息和具体做法。 Caleb Porzio 发推庆祝自己靠 GitHub 打赏(GitHub Sponsors)赚到了 10 万美元。 GitHub Sponsors是 GitHub 2019 年 5 月份推出的一个功能,允许开发…...
剖析Spring MVC如何将请求映射到Controller
Spring MVC是一种基于Java的Web框架,可以帮助开发者快速地构建Web应用程序。在Spring MVC中,请求将会被映射到对应的Controller中进行处理。本文将会介绍Spring MVC如何将请求映射到Controller的过程。 DispatcherServlet DispatcherServlet是Spring M…...
设计模式之美-工厂模式
分类:简单工厂模式(静态工厂模式),工厂方法模式,抽象工厂模式。 这种设计模式也是 Java 开发中最常见的一种模式,它的主要意图是定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类&a…...
A Star算法最通俗易懂的一个版本
01-概述虽然掌握了 A* 算法的人认为它容易,但是对于初学者来说, A* 算法还是很复杂的。02-搜索区域(The Search Area)我们假设某人要从 A 点移动到 B 点,但是这两点之间被一堵墙隔开。如图 1 ,绿色是 A ,红色是 B &…...
JavaWeb--ListenerAjaxaxiosjson
Listener&Ajax&axios1 Listener1.1 概述1.2 分类1.3 代码演示2 Ajax2.1 概述2.1.1 作用2.1.2 同步和异步2.2 快速入门2.2.1 服务端实现2.2.2 客户端实现2.2.3 测试2.3 案例2.3.1 分析2.3.2 后端实现2.3.3 前端实现2.4 测试3 axios3.1 基本使用3.2 快速入门3.2.1 后端实…...
NoneBot2,基于Python的聊天机器人
NoneBot2,基于Python的聊天机器人第一步,配置python第二步,配置[go-cqhttp](https://github.com/Mrs4s/go-cqhttp)第三步,配置[NoneBot](https://61d3d9dbcadf413fd3238e89--nonebot2.netlify.app/)NoneBot2 是一个现代、跨平台、…...
java反射机制及其详解
反射反射机制反射调用优化有时候我们做项目的时候不免需要用到大量配置文件,就拿框架举例,通过这些外部文件配置,在不修改的源码的情况下,来控制文件,就要用到我们的反射来解决 假设有一个Cat对象 public class Cat …...
Leetcode—环形链表
前言:给定一个链表,判断是否为循环链表并找环形链表的入口点 首先我们需要知道什么是双向循环链表,具体如下图所示。 对于链表,我们如何去判断链表是循环链表呢?又寻找入环点呢?我们可以利用快慢指针的方法…...
蓝牙耳机哪个戴的最舒服?久戴不累的蓝牙耳机推荐
在喧嚣的时代中,快节奏和疲惫充斥着我们的生活,于是耳机成为了人们必不可少的东西,无论是闲暇时亦或是正处在工作时,都会将它戴上,出门在外戴耳机变成了常态,所以小编就整理了一期久戴不累的蓝牙耳机。 No…...
25k的Java开发常问的AQS问题有哪些?
前言:面试高频的AQS问题大多。本文将以实战面试角度出发,将面试官喜欢问的一些问题罗列出来。 文章目录 AQSAQS定义底层实现独占锁举例底层实现独占锁超时获取锁共享锁举例共享锁实现原理作者辟谣AQS AQS定义 AQS的全称是AbstractQueuedSynchronizer,也就是抽象队列同步器…...
Grafana 监控面板绘制流程
本篇作者:IoTDB 社区 -- 张洪胤本文以 IoTDB V1.0.1 版本为例本文档介绍了 Apache IoTDB 监控指标通过 Prometheus 的方式进行采集,并且使用 Grafana 的方式进行可视化。1监控指标的 Prometheus 格式说明对于 Metric Name 为 name, Tags 为 K1V1, ..., K…...