【C++】15. 模板进阶
1. 非类型模板参数
模板参数分类类型形参与非类型形参。
类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常 量来使用。
namespace Ro
{// 定义一个模板类型的静态数组template<class T, size_t N = 10>class array{public:T& operator[](size_t index) { return _array[index]; }const T& operator[](size_t index)const { return _array[index]; }size_t size()const { return _size; }bool empty()const { return 0 == _size; }private:T _array[N];size_t _size;};
}
在这里 N 就是一个非类型模板参数,是一个常量,使用的时候传多大就是多大,不会直接写死大小。
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的,不过在C++20之后可以使用浮点数作为非类型模板参数
2. 非类型的模板参数必须在编译期就能确认结果。
说到array类,那我们就来介绍一下它
说白了就是在底层封装了一个静态数组。但是呢,比静态数组要强一点,但是和vector比又显得很鸡肋
在C++中,静态数组(内置数组)和std::array
类(来自STL)都是用于存储固定大小的数据集合,但它们在功能、安全性和用法上有显著区别。以下是详细对比:
1. 类型定义与声明
-
静态数组(内置数组):
直接使用原生语法声明,例如:int arr[5]; // 静态数组,大小为5 int arr2[] = {1, 2, 3}; // 自动推断大小为3
-
std::array
类:
需包含头文件<array>
,并显式指定类型和大小:#include <array> std::array<int, 5> arr; // 大小为5的array对象 std::array<int, 3> arr2 = {1, 2, 3};
2. 类型安全性
-
静态数组:
-
作为函数参数传递时会退化为指针(丢失大小信息),例如:
void func(int arr[]); // 实际接受的是指针,无法知道数组大小
-
容易因隐式指针转换导致未定义行为。
-
-
std::array
类:-
作为对象传递时保留完整类型信息(包括大小),例如:
void func(std::array<int, 5>& arr); // 明确知道大小和类型
-
类型严格匹配,避免隐式转换错误。
-
3. 访问元素
-
静态数组:
-
使用下标
arr[i]
或指针算术直接访问。 -
无越界检查,越界访问可能导致未定义行为。
-
-
std::array
类:-
支持下标
arr[i]
(不检查越界,性能与原生数组相同)。 -
提供
.at(i)
方法(进行越界检查,越界时抛出std::out_of_range
异常)。 -
提供便捷的成员函数:
front()
、back()
等。
-
4. 成员函数与功能
-
静态数组:
-
无成员函数,需手动实现常见操作(如复制、比较等)。
-
大小需通过
sizeof(arr)/sizeof(arr[0])
计算(易出错)。
-
-
std::array
类:-
提供丰富的成员函数:
arr.size(); // 返回元素数量(编译时常量) arr.empty(); // 检查是否为空 arr.fill(42); // 填充相同值 arr.swap(arr2); // 交换两个array的内容
-
支持迭代器:
for (auto it = arr.begin(); it != arr.end(); ++it) { ... } // 或范围for循环 for (auto& x : arr) { ... }
-
5. 赋值与复制
-
静态数组:
-
不能直接赋值,必须逐个元素复制:
int arr1[3] = {1, 2, 3}; int arr2[3]; // arr2 = arr1; // 错误! std::copy(arr1, arr1+3, arr2); // 需要手动复制
-
-
std::array
类:-
支持直接赋值(深拷贝):
std::array<int, 3> arr1 = {1, 2, 3}; std::array<int, 3> arr2; arr2 = arr1; // 合法,整体复制
-
6. 作为函数返回值
-
静态数组:
-
无法直接返回,通常需返回指针或封装为结构体。
-
-
std::array
类:-
可直接返回,无需额外操作:
std::array<int, 3> create_array() {return {1, 2, 3}; }
-
7. 内存与性能
-
相同点:
-
两者均在栈上分配内存(除非显式动态分配)。
-
访问速度相同(
operator[]
无额外开销)。
-
-
不同点:
-
std::array
的.at()
方法因边界检查有轻微性能损失,但提供安全性。
-
8. 兼容性
-
静态数组:
-
兼容C语言,适合与C代码交互。
-
-
std::array
类:-
仅限C++11及以上版本,需支持STL的编译器。
-
总结对比表
特性 | 静态数组 | std::array 类 |
---|---|---|
类型安全性 | 弱(退化为指针) | 强(保留大小和类型) |
越界检查 | 无 | 支持(通过 .at() ) |
成员函数 | 无 | 丰富(size() , fill() , 等) |
赋值操作 | 不支持直接赋值 | 支持整体赋值 |
迭代器支持 | 需手动处理指针 | 支持STL迭代器 |
作为返回值 | 需额外处理 | 直接支持 |
兼容性 | 兼容C | 仅限C++11+ |
使用建议
-
优先使用
std::array
:
在C++11及以上环境中,推荐使用std::array
,因其安全性、功能性和与现代STL的兼容性。 -
静态数组适用场景:
-
需要与C代码交互时。
-
对旧代码兼容性要求较高时。
-
2.模板的特化
2.1 概念
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{return left < right;
}int main()
{cout << Less(1, 2) << endl; // 可以比较,结果正确Date d1(2025, 4, 26);Date d2(2025, 4, 27);cout << Less(d1, d2) << endl; // 可以比较,结果正确Date* p1 = new Date(2025, 4, 26);Date* p2 = new Date(2025, 4, 27);cout << Less(p1, p2) << endl; // 可以比较,结果错误return 0;
}
可以看到,Less绝对多数情况下都可以正常比较,但是在特殊场景下就得到错误的结果。上述示例中,p1指向的d1显然小于p2指向的d2对象,但是Less内部并没有比较p1和p2指向的对象内容,而比较的是p1和p2指针的地址,这就无法达到预期而错误。 此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化与类模板特化。
2.2 函数模板特化
函数模板的特化步骤:
1. 必须要先有一个基础的函数模板
2. 关键字template后面接一对空的尖括号<>
3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误
// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{return *left < *right;
}
只要特化一下,比较的就不是地址了,编译器这里会优先调用特化版本的Less,毕竟编译器也知道省点懒,有现成的就用现成的。
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出。
bool Less(Date* left, Date* right)
{return *left < *right;
}
三者都存在时,编译器会优先走函数重载,因为函数重载是直接能用的,比函数模板特化更加现成
该种实现简单明了,代码的可读性高,容易书写,因为对于一些参数类型复杂的函数模板,特化时特别给出,因此函数模板不建议特化。
2.3 类模板特化
2.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;
};
void Test1()
{Data<int, int> d1;Data<int, char> d2;
}
当两个类模板传的类型不同时,我们就需要全特化
2.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; }
};void Test2()
{Data<int, int> d1;Data<char, 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 Test3()
{Data<double, int> d1; // 调用特化的int版本Data<int, double> d2; // 调用基础的模板Data<int*, int*> d3; // 调用特化的指针版本Data<int&, int&> d4(1, 2); // 调用特化的指针版本
}
3 模板分离编译
3.1 什么是分离编译
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有 目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。
3.2 模板的分离编译
假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:
// a.h
template<class T>
T Add(const T& left, const T& right);
// a.cpp
template<class T>
T Add(const T& left, const T& right)
{return left + right;
}
// main.cpp
#include"a.h"
int main()
{Add(1, 2);Add(1.0, 2.0);return 0;
}
分析:
3.3 解决方法
1. 将声明和定义放到一个文件 "xxx.hpp" 里面或者xxx.h其实也是可以的。推荐使用这种。
2. 模板定义的位置显式实例化。这种方法不实用,不推荐使用。
【分离编译扩展阅读】
http://blog.csdn.net/pongba/article/details/19130
4.模板的优缺点
一、模板的优点
1. 代码复用与泛化
-
泛型编程:
允许编写与类型无关的代码,适用于多种数据类型。
例如:std::vector<T>
可以存储任意类型的元素,无需为每种类型重复实现容器逻辑。 -
减少冗余:
避免为相似逻辑但不同数据类型的函数或类编写重复代码(如排序、交换等操作)。
2. 类型安全
-
编译时类型检查:
模板在实例化时会生成具体类型的代码,编译器会进行严格的类型匹配,避免运行时类型错误。
例如:std::vector<int>
和std::vector<double>
是完全不同的类型,不能隐式转换。
3. 性能优化
-
编译时多态:
通过模板展开生成具体类型的代码,无需运行时虚函数表(vtable)查找,性能接近手写代码。
例如:std::sort
的模板实现比运行时多态的排序算法更快。 -
零成本抽象:
模板的高效性使得抽象(如STL容器和算法)几乎不带来额外性能开销。
4. 灵活性
-
支持元编程:
模板元编程(TMP)允许在编译时进行计算和类型推导,实现高度优化的逻辑(如编译时条件判断、循环展开等)。
例如:std::tuple
的递归实现和std::enable_if
的条件编译。 -
与类型系统结合:
可以结合constexpr
、concepts
(C++20)等特性,实现更复杂的编译时逻辑。
5. 标准库支持
-
STL的基石:
标准模板库(STL)完全基于模板构建,提供了通用的容器(vector
、map
)、算法(sort
、find
)和迭代器。
二、模板的缺点
1. 编译时间膨胀
-
代码生成开销:
每个模板实例化都会生成独立的代码,若模板被频繁用于不同类型,可能导致编译后二进制文件体积增大(代码膨胀)。
例如:std::vector<int>
和std::vector<double>
会生成两份完全不同的机器码。 -
编译速度下降:
模板的递归展开和复杂实例化逻辑会显著增加编译时间,尤其是大型项目或深度嵌套的模板。
2. 错误信息晦涩
-
难以调试的报错:
模板错误通常会在实例化时暴露,编译器报错信息冗长且难以理解,尤其是涉及嵌套模板或元编程时。
例如:一个简单的类型不匹配可能导致数十行的错误链。
3. 代码可读性降低
-
语法复杂性:
模板语法(如typename
依赖、特化规则)对初学者不友好,复杂模板代码可能难以维护。
例如:template <typename T> using EnableIf = typename std::enable_if<...>::type;
-
元编程的隐式逻辑:
模板元编程依赖编译时计算,逻辑可能隐藏在类型推导和特化中,增加理解成本。
4. 跨平台兼容性挑战
-
编译器差异:
不同编译器对模板的支持可能存在差异(如旧版本编译器对C++11/14/17特性的支持不完整),导致移植性问题。
5. 运行时动态性受限
-
编译时确定类型:
模板的类型必须在编译时确定,无法实现真正的运行时多态(需结合虚函数或类型擦除技术如std::any
)。
三、使用场景与替代方案
1. 适用场景
-
需要高度复用且类型无关的代码(如容器、算法)。
-
对性能要求严格的场景(如数值计算、游戏引擎)。
-
编译时逻辑优化(如条件编译、静态检查)。
2. 替代方案
-
运行时多态(虚函数):
适用于需要动态类型或接口统一的场景,但会引入运行时开销。 -
宏(Macro):
简单代码生成,但缺乏类型安全且难以调试(不推荐替代模板)。 -
C++20概念(Concepts):
增强模板的类型约束,提升错误信息的可读性。
四、总结
优点 | 缺点 |
---|---|
代码复用与泛化 | 编译时间膨胀 |
类型安全 | 错误信息晦涩 |
高性能(编译时多态) | 代码可读性降低 |
灵活支持元编程 | 跨平台兼容性挑战 |
与STL深度集成 | 运行时动态性受限 |
五、最佳实践
-
优先使用STL:避免重复造轮子,直接使用标准库中的模板组件。
-
限制模板复杂度:避免过度使用元编程,保持代码可维护性。
-
结合C++20概念:使用
concepts
约束模板参数,提升代码清晰度和错误信息质量。 -
类型萃取与SFINAE:合理使用
std::enable_if
或if constexpr
实现条件编译。 -
模块化设计:将模板声明与实现分离到头文件中,减少编译依赖。
模板是C++的核心特性之一,正确使用可以大幅提升代码的灵活性和效率,但需权衡其复杂性和编译成本。在性能关键型项目和泛型库开发中,模板几乎是不可替代的工具;而在需要动态多态或快速迭代的场景中,需谨慎选择其使用范围。
相关文章:
【C++】15. 模板进阶
1. 非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当…...
C#进阶学习(十四)反射的概念以及关键类Type
目录 本文末尾有相关类中的总结,如有需要直接跳到最后即可 前置知识: 1、程序集(Assembly) 2、元数据(Metadata) 3、中间语言(IL, Intermediate Language) 中间语言(…...
B. And It‘s Non-Zero
题目链接:https://codeforces.com/problemset/problem/1615/B 位运算之前没怎么写过,所以不会写。留一份题解,作为复习使用。 题解:按位与的结果不为0,则至少有一列全为1.要求删除的数最少,即要求该列原本…...
深入解析NuttX:为何它是嵌入式RTOS领域的标杆?
文章目录 引言一、NuttX简介:轻量级与高兼容性的结合二、架构特点:为何NuttX更灵活?三、横向对比:NuttX vs 主流嵌入式RTOS四、NuttX的核心优势五、何时选择NuttX?结语 引言 在资源受限的嵌入式系统中,实时…...
html初识
html 盖楼第一步:HTML1. HTML是啥玩意儿?2. 动手!搭个你的"网络小窝" (第一个HTML页面)3. 添砖加瓦:常用HTML"建材"详解3.1 标题家族3.2 段落哥俩好3.3 传送门:链接3.4 挂画:图片 盖楼…...
leetcode66.加一
从后向前遍历,直到碰到非9的数(也就是数组中中最后一个非9的数) ,该值+1,然后其后的数字全部0 class Solution {public int[] plusOne(int[] digits) {for (int i digits.length-1; i >0; i--) {if (d…...
【Vue】Vue3项目创建
执行npm run dev,如果报错检查nodejs版本...
缓存替换算法之 FIFO(先进先出)
FIFO(First In, First Out,先进先出)是一种常见的缓存替换算法,其基本思想是最早进入缓存的数据项将最先被移除。以下是FIFO的详细讲解: 一、FIFO的数据结构 队列(Queue) 队列是一种典型的线性…...
Linux下的I/O复用技术之epoll
I/O多路复用 指在单个线程或进程中,同时处理多个I/O操作的技术。 旨在提高程序处理多个并发I/O操作的能力,避免程序因等待某个I/O操作而被阻塞。在传统的I/O模型中当程序进行I/O操作时(如读取文件、接受网路数据等),如果数据还未准备好&…...
数据分析管理软件 Minitab 22.2.2 中文版安装包 免费下载
Minitab22.2.2 安装包下载链接: https://pan.baidu.com/s/1cWuDbvcWhYrub01C6QR81Q?pwd6666 提取码: 6666 Minitab软件是现代质量管理统计软件,全球六西格玛实施的共同语言。Minitab 已经在全球120多个国家,5000多所高校被广泛使用。...
chrony服务器(1)
简介 NTP NTP(Network Time Protocol,网络时间协议)是一种用于同步计算机系统时间的协议是TCP/IP协议族中的一个应用层协议,主要用于在分布式时间服务器和客户端之间进行时钟同步,提供高精准度的时间校正通过分层的时…...
2025.04.26-淘天春招笔试题-第三题
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 二进制信号转换器 问题描述 卢小姐是一位通信工程师,她设计了一种特殊的二进制信号处理装置。该装置可以对由 0 0 0...
腾讯二面:TCC分布式事务 | 图解TCC|用Go语言实现一个TCC
写在前面 前段时间,有同学反馈的一个面试问题,觉得分布式事务有点偏了,但其实也不算偏了,在java领域就有很火很成熟的seata分布式事务框架(阿里和蚂蚁的同学主导,目前在apache孵化)。 之前我们讲过了两阶段提交、三阶…...
如何在 Conda 环境中降级 Python 版本:详细指南
如何在 Conda 环境中降级 Python 版本:详细指南 Python 版本的管理在开发过程中至关重要,特别是在处理不同项目需求时。对于使用 Conda 环境的 Python 程序员来说,版本管理不仅仅是安装不同的 Python 版本,还涉及到依赖关系的兼容…...
MCP 协议解读:STDIO 高效通信与 JSON-RPC 实战
本文深度解析 MCP 协议的传输机制与消息格式,涵盖 stdio、SSE 及自定义传输方式,剖析 JSON-RPC 2.0 的请求、响应与通知设计。 结合 RooCode 开源实现与天气查询案例,揭秘如何通过 MCP 实现跨进程通信与高效服务集成,为开发者提供…...
AI心理健康服务平台项目面试实战
AI心理健康服务平台项目面试实战 第一轮提问: 面试官: 请简要介绍一下AI心理健康服务平台的核心技术架构。在AI领域,心理健康服务的机遇主要体现在哪些方面?如何利用NLP技术提升用户与AI的心理健康对话体验? 马架构…...
路由器重分发(OSPF+RIP),RIP充当翻译官,OSPF充当翻译官
路由器重分发(OSPFRIP) 版本 1 RIP充当翻译官 OSPF路由器只会OSPF语言;RIP路由器充当翻译官就要会OSPF语言和RIP语言;则在RIP中还需要将OSPF翻译成RIPOSPF 把RIP路由器当成翻译官,OSPF路由器就只需要宣告自己的ip&am…...
29-算法打卡-字符串-KMP算法理论2-第二十九天
1、KMP算法前缀表计算逻辑 可以查看上一章节的前缀表概念以及逻辑,KMP算法基础理论[基础概念、前缀、后缀、最长公共前后缀、前缀表] 2、KMP算法前缀表使用 当模式串和文本串匹配失败的时候,前缀表会告诉我们下一次的匹配中,模式串应该跳到…...
解锁生成式AI潜力的金钥匙
一、引言:生成式AI的浪潮与“提示词”的崛起 在短短几年内,生成式人工智能(Generative AI)以前所未有的速度席卷全球,从文字创作到图像生成,从代码辅助到科学研究,以ChatGPT、Midjourney、DALL…...
统计定界子数组的数组
前言:看到这个题目的时候,只想着怎么暴力枚举右端点,结合线段树还是会超时,没找到很好的处理方法 超时代码 class Tree1:def __init__(self,n):self.t [0]*(4*n)def update(self,o,l,r,index,va):if lr:self.t[o] vareturnmid …...
JAVA---字符串
ctrlN 搜索界面(idea) API和API帮助文档 API : 应用程序编程接口(换句话说,就是别人已经写好了,我们不需要再编写,直接使用即可) Java API :就是JDK中提供的各种功能…...
import tree # pip install dm_tree ModuleNotFoundError: No module named ‘tree‘
在导入tree包时,在python库里找了很久,一直以为是tree这个包没下载好,有的推荐执行 pip install dm_tree这是deepmind开发一个处理处理嵌套数据结构的库。它在某种程度上tree 概括了仅支持扁平序列的内置map函数,并允许将函数应用…...
Java ThreadLocal与内存泄漏
当我们利用 ThreadLocal 来管理数据时,我们不可避免地会面临内存泄漏的风险。 原因在于 ThreadLocal 的工作方式。当我们在当前线程的 ThreadLocalMap 中存储一个值时,一旦这个值不再需要,释放它就变得至关重要。如果不这样做,那么…...
Rule.resource作用说明
1. 说明 作用 Rule.resource 用于定义哪些文件需要被当前规则处理。它是对传统 test、include、exclude 的更底层封装,支持更灵活的匹配方式。 与 test/include/exclude 的关系 test: /.js$/ 等价于resource: { test: /.js$/ } include: path.resolve(__dirname, ‘…...
【Docker项目实战】使用Docker部署Caddy+vaultwarden密码管理工具(详细教程)
【Docker项目实战】使用Docker部署vaultwarden密码管理工具 前言一、vaultwarden介绍1.1 vaultwarden简介1.2 主要特点二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、拉取镜像五、…...
代码随想录算法训练营第五十九天 | 1.ford算法精讲 卡码网94.城市间货物运输
1.Bellman_ford 算法精讲 题目链接:94. 城市间货物运输 I 文章讲解:代码随想录 思路: 使用dijkstra,要求图中边的权值都为正数。 带负权值的单源最短路问题,轮到Bellman_ford 算法。Bellman_ford算法的核心思想是对…...
shell(1)
1.shell变量介绍 i.Linux Shell中的变量分为,系统变量和用户自定义变量. ii.系统变量:$HOME,$PWD, $SHELL,$USER 例echo $HOME iii.显示当前shell中的所有变量--set 2.shell变量的定义 基本语法 1.定义变量:变量名值 注意 号左右也不能有空格 2.撤销变量:unset 变量 3.声…...
KEPServerEX 6与西门子1500PLC进行OPC通讯
仿真效果与真实环境效果一至; 环境: 西门子软件:博图V20、S7-PLCSIM Advanced V5.0 OPC软件:KEPServerEX 6 创建S7-PLCSIM Advanced V5.0仿真环境 西门子1500plc组态 添加一个1500cpu,注意点击项目文件࿰…...
【概念】什么是 JWT Token?
—什么是 JWT Token? JWT Token(JSON Web Token) 就是一张后端发给前端的小票,里面包含用户身份信息,用于做无状态认证(Stateless Authentication)。 每次前端访问后端接口,都拿着…...
【Castle-X机器人】一、模块安装与调试:机器人底盘
持续更新。。。。。。。。。。。。。。。 【ROS机器人】模块安装 一、Castle-X机器人底盘1.1 结构概述1.2 驱动执行结构1.3 环境传感器1.4 电气系统1.5 Castle-x机器人底盘测试激光雷达传感器测试及数据可视化超声波传感器实时数据获取防跌落传感器测试陀螺仪测试键盘控制测试…...
NSIS打包
以下是一篇详细的 NSIS 打包 EXE 的入门教程: NSIS 打包 EXE 入门教程 NSIS(Nullsoft Scriptable Install System)是一款开源的 Windows 安装包制作工具,支持脚本化定制安装流程。本教程将带你从零开始,创建一个简单的 EXE 安装程序。 1. 环境准备 1.1 下载 NSIS 访问官…...
62.不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示例 …...
前端开发中shell的使用场景
Shell语言基础概念 Shell是用户与操作系统内核之间的接口,它接收用户输入的命令并解释执行。在Linux/Unix系统中,Shell是最常用的命令行界面。 基本语法和常用命令 变量定义和使用 # 定义变量 name"张三" age25# 使用变量 echo $name echo…...
基于javaweb的SSM投票管理系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...
uml类关系(实现、继承,聚合、组合,依赖、关联)
drawio和EA是架构设计时经常使用的画图工具。 drawio学习门槛低,使用灵活,但是功能仅仅限于画图。 EA学习门槛高,但是功能更加的丰富: ①在画图方面,EA严格满足UML标准,EA中的图和类是关联的,…...
力扣热题100题解(c++)—链表
160.相交链表 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数…...
MQ消息的不可靠性发生情况与解决方案
文章目录 问题:可能出现的情况: 解决流程与兜底方案第一个方面:确保生产者一定把消息发送到MQ1.生产者重试机制2.生产者确认机制 第二个方面:确保MQ不会将消息丢失数据持久化交换机持久化2.队列持久化3.消息持久化 LazyQueue控制台…...
线程池(五):线程池使用场景问题
线程池(五):线程池使用场景问题 线程池(五):线程池使用场景问题1 线程池使用场景CountDownLatch、Future1.1 CountDownLatch原理示例代码 1.2 案例一(es数据批量导入)需求分析实现步…...
第十六届蓝桥杯网安初赛wp
解题列表 根据提示一步一步走,经过猜测,测试出app.py 经过仔细研读代码,找到密钥 编写python代码拿到flag key secret_key9828 flagd9d1c4d9e0d6c29e9aad71696565d99bc8d892a8979ec7a69b9a6868a095c8d89dac91d19ba9716f63b5 newbytearray(…...
8.学习笔记-Maven进阶(P82-P89)
(一)Maven-08-配置文件加载属性 通过maven可以做版本的集中管理,所以能不能通过maven进行配置文件(jdbc.properties)的集中管理。 (1)resource-》jdbc.properties 可以识别$符号 因为只能…...
基于 IPMI + Kickstart + Jenkins 的 OS 自动化安装
Author:Arsen Date:2025/04/26 目录 环境要求实现步骤自定义 ISO安装 ipmitool安装 NFS定义 ks.cfg安装 HTTP编写 Pipeline 功能验证 环境要求 目标服务器支持 IPMI / Redfish 远程管理(如 DELL iDRAC、HPE iLO、华为 iBMC)&…...
Ubuntu20.04部署Ragflow(Docker方式)
Ubuntu20.04部署Ragflow(Docker方式) Ubuntu20.04 RagflowRunning RagflowRunning Ollama 由于写这篇博客的时候电脑还没装输入法,所以先用半吊子英文顶着了…关于最后运行ollama的部分可以无视,因为我修改了端口所以才需要这么运…...
【C++语法】类和对象(2)
4.类和对象(2) 文章目录 4.类和对象(2)类的六个默认成员函数(1)构造函数:构造函数特点含有缺省参数的构造函数构造函数特点(续)注意事项构造函数补充 前面总结了有关对象概念,对比 C…...
JDK 17 与 Spring Cloud Gateway 新特性实践指南
一、环境要求与版本选择 1. JDK 17 的必要性 最低版本要求:Spring Boot 3.x 及更高版本(如 3.4)强制要求 JDK 17,以支持 Java 新特性(如密封类、模式匹配)和性能优化。JDK 17 核心特性: 密封类…...
深入了解及掌握AppScan不同测试策略的区别
引言 在当今数字化时代,应用程序安全至关重要。IBM AppScan作为一款强大的应用安全测试工具,提供了多种测试策略以适应不同的测试场景和需求。理解这些测试策略的区别,能够帮助安全测试人员更精准地开展测试工作,发现应用程序中潜藏的安全漏洞。本文将结合实际案例,深入剖…...
【Linux】web服务器的部署和优化
目录 nginx的安装与启用--/usr/share/nginx/html默认发布目录 nginx的主配置文件--/etc/nginx/nginx_conf nginx的端口 nginx默认发布文件--index.html nginx默认发布目录 nginx的访问控制 基于IP地址的访问控制 基于用户认证的访问控制 nginx的虚拟主机--/etc/nginx/…...
20250426在ubuntu20.04.2系统上解决问题mkfs.exfat command not found
20250426在ubuntu20.04.2系统上解决问题mkfs.exfat command not found 2025/4/26 21:11 缘起,使用NanoPi NEO开发板,编译FriendlyCore系统,打包eMMC固件的时候报错。 ./build.sh emmc-img -pack sd-card image, used to write frie…...
IDE使用技巧与插件推荐
一、高效使用技巧 1. 快捷键与操作优化 VS Code: 快速导航:Ctrl+P(Windows/Linux)或Cmd+P(macOS)打开文件搜索,输入文件名快速定位。多光标编辑:按住Alt(Windows/Linux)或Option(macOS)点击多个位置,同时编辑多处代码。Zen 模式:Ctrl+K Z(Windows/Linux)或Cmd…...
防火墙规则配置错误导致的网络问题排查
# 防火墙规则配置错误导致的网络问题排查指南 防火墙规则配置错误是网络连接问题的常见原因之一。以下是一套系统的排查步骤和方法: ## 1. 初步症状确认 - **常见表现**: - 特定服务无法访问 - 网络连接时断时续 - 部分IP地址或端口无法通信 …...
线性代数(一些别的应该关注的点)
一、矩阵 矩阵运算:线性变换 缩放、平移、旋转 无所不能的矩阵 - 三维图形变换_哔哩哔哩_bilibili...