C++ 元编程
目录
- C++ 元编程
- 1. 术语
- 2. 元函数
- 1. 数值元函数
- 示例:阶乘计算
- 2. 类型元函数
- 示例:类型选择
- 3. 混合编程
- 1. 常规的计算点积范例
- 2. 混合元编程计算点积
- 4. typelist实现
- 设计和基本操作接口(算法)
- 完整代码
- 5. tuple 实现
- 基础知识
- 1. 左值、右值、左值引用、右值引用
- 2. std::move 究竟做了什么
- 3. std::forward 究竟做了什么
- 4. 万能引用(转发引用)
- 5. 完美转发
- tuple 实现示例
C++ 元编程
元编程的主要目的在于将各种计算从运行期提前至编译期进行,以实现程序运行时的性能提升。也正因如此,元编程是一种增加程序的编译时间,从而提升程序运行效率的编程技术。
在元编程中,涉及许多与循环相关的代码。传统编程中,循环通常采用 for
、while
等语句实现,这些语句一般针对的是运行期的条件变量;而在元编程中,更多的操作其实是针对类型或常量的。这种循环的实现往往会采用递归的手段,使得编译器能够在编译期间完成某些计算。
1. 术语
元编程的英文名称是 Meta Programming,有时也称为 模板元编程(Template Metaprogramming)。可以理解为一种编程手法,用于实现一些比较特殊的功能。元编程与“递归”这一概念紧密相连,代表着在元编程中,大多数情况下都会使用递归编程技术。
模板编程主要应用在泛型编程和元编程:
泛型编程(Generic Programming)强调的是“通用”的概念,旨在通过抽象和参数化来实现代码的复用与灵活性。在泛型编程中,程序员可以编写与类型无关的算法和数据结构,使得同一段代码能够适用于多种类型。模板的设计初衷正是为了满足这一需求。
元编程(Meta Programming)则是一种更高级的编程技巧,旨在通过编译期间的计算和推导来实现某些功能。元编程允许程序员在编译期进行复杂的逻辑处理,通常这些逻辑在运行时才能完成。
2. 元函数
传统的函数都是在程序运行期间被调用和执行的函数,而元函数是能在程序编译期间被调用和执行的函数(编译期间就能得到结果)。引入元函数概念的目的是支持元编程,而元编程的核心也正是元函数。
1. 数值元函数
数值元函数是在编译期间对数值进行计算的元函数。这类元函数可以接收整型常量作为模板参数,并根据这些常量进行编译时计算。数值元函数通常用于实现一些数学运算,如阶乘、斐波那契数列等。
示例:阶乘计算
template<int N>
struct Factorial {static const int value = N * Factorial<N - 1>::value;
};template<>
struct Factorial<0> {static const int value = 1;
};// 使用
constexpr int fact5 = Factorial<5>::value; // fact5 的值为 120
std::cout << fact5 << std::endl; // 输出 120
2. 类型元函数
类型元函数则是针对类型进行操作的元函数。它们允许程序员在编译期间对类型进行推导、选择和变换。这类元函数非常适合于类型特征提取和类型转换等场景。
示例:类型选择
template<bool Condition, typename TrueType, typename FalseType>
struct Conditional;template<typename TrueType, typename FalseType>
struct Conditional<true, TrueType, FalseType> {using type = TrueType;
};template<typename TrueType, typename FalseType>
struct Conditional<false, TrueType, FalseType> {using type = FalseType;
};// 使用
using ResultType = Conditional<true, int, double>::type; // ResultType 的类型为 int
3. 混合编程
混合编程是结合了运行时和编译时计算的技术,允许程序员在编译期间进行一些运算,同时时间复杂度也得到优化。混合编程的关键在于利用模板和递归来处理类型和数值,使得某些操作可以在编译期完成,从而提高运行时性能。
1. 常规的计算点积范例
混合元编程方面,一个比较典型的案例是计算两个向量(数组)点积。
(1)数组a有3个元素a[0]、a[1]、a[2],值分别为1、2、3;
(2)数组b有3个元素b[0]、b[1]、b[2],值分别为4、5、6;
(3)a和b的点积是一个数值,结果为a[0]×b[0] + a[1] ×b[1] + a[2] ×b[2] =1×4+2×5+3×6=32。
在传统编程中,计算两个数组(向量)的点积通常使用循环结构,如for
或while
。以下是一个简单的点积计算示例:
#include <iostream>template<typename T, int U>
auto DotProduct(T* array1, T* array2)
{T dpresult = T{};for (int i = 0; i < U; ++i){dpresult += array1[i] * array2[i];}return dpresult;
}int main()
{int a[] = { 1,2,3 };int b[] = { 4,5,6 };int result = DotProduct<int, 3>(a, b);std::cout << result << std::endl; // 输出 32return 0;
}
2. 混合元编程计算点积
通过元编程,可以在编译期间计算点积。下面的代码展示了如何使用模板和递归实现这一点:
#include <iostream>//泛化版本
template<typename T, int U> //T:元素类型,U:数组大小
struct DotProduct
{static T result(const T* a, const T* b){return (*a) * (*b) +DotProduct<T, U - 1>::result(a + 1, b + 1);}
};
//特化版本,作为递归调用的出口
template<typename T>
struct DotProduct<T, 0>
{static T result(const T *,const T*){return T{};}
};int main()
{int a[] = { 1,2,3 };int b[] = { 4,5,6 };int result = DotProduct<int, 3>::result(a, b);std::cout << result << std::endl;return 0;
}
- 泛化版本:
DotProduct
是一个模板类,它接受元素类型T
和数组大小U
作为模板参数。result
函数是一个静态成员函数,通过递归调用来计算点积。它取当前元素*a
和*b
的乘积,并加上对下一个元素的递归调用。
- 特化版本:
- 当
U
为0
时,递归调用的出口到达。此时返回一个默认初始化的值T{}
,表示点积计算的结束。
- 当
4. typelist实现
typelist的解释为:用来操作一大堆类型的C++容器,就像C++标准库中的list容器能够为数值提供各种基本操作一样(只不过这里操作的不是数值,而是类型)。
从实现上来讲,typelist是一个类模板,译为“类型列表”,这个类模板用来表示一个列表,这个列表中存放着一堆类型。
设计和基本操作接口(算法)
Typelist 的基本定义
template<typename... Types>
struct TypeList {};// 基本类型操作
using EmptyTypeList = TypeList<>; // 空类型列表
1. 取得typelist中的第1个元素(front)
这个操作返回 typelist
中的第一个类型。通过模板特化,可以在编译时获取到这个类型。该操作通常用于获取类型链的起始类型,以便后续处理。
template<typename TList>
struct Front;template<typename Head, typename... Tail>
struct Front<TypeList<Head, Tail...>> {using type = Head; // 返回第一个元素
};
2. 取得typelist容器中元素的数量(size)
这个操作计算并返回 typelist
中包含的类型数量。它使用可变参数模板的特性,通过 sizeof...
来计算类型的数量。
template<typename TList>
struct Size;template<typename... Types>
struct Size<TypeList<Types...>> {static const size_t value = sizeof...(Types); // 元素计数
};
3. 从typelist中移除第1个元素(pop_front)
此操作会返回一个新的 typelist
,该列表中不再包含第一个类型。它通过递归去掉开头的类型,为后续操作提供了简化的列表。
template<typename TList>
struct PopFront;template<typename Head, typename... Tail>
struct PopFront<TypeList<Head, Tail...>> {using type = TypeList<Tail...>; // 移除第一个元素
};
4. 向typelist的开头和结尾插入一个元素(push_front和push_back)
- push_front: 将新类型插入到
typelist
的开头,产生一个新的typelist
。 - push_back: 将新类型插入到
typelist
的结尾,同样产生一个新的typelist
。
template<typename TList, typename NewType>
struct PushFront;template<typename... Types, typename NewType>
struct PushFront<TypeList<Types...>, NewType> {using type = TypeList<NewType, Types...>; // 插入到开头
};template<typename TList, typename NewType>
struct PushBack;template<typename... Types, typename NewType>
struct PushBack<TypeList<Types...>, NewType> {using type = TypeList<Types..., NewType>; // 插入到结尾
};
5. 替换typelist的开头元素(replace_front)
此操作允许替换 typelist
的第一个类型为一个新的类型,并返回一个新的 typelist
。这对于动态更改类型列表的开头非常有用。
template<typename TList, typename NewType>
struct ReplaceFront;template<typename... Tail, typename NewType>
struct ReplaceFront<TypeList<Tail...>, NewType> {using type = TypeList<NewType, Tail...>; // 替换开头元素
};
6. 判断typelist是否为空(is_empty)
此操作检查 typelist
是否包含任何类型。如果列表为空,返回 true
,否则返回 false
。这是确保操作安全性的重要步骤。
template<typename TList>
struct IsEmpty;template<>
struct IsEmpty<EmptyTypeList> {static const bool value = true; // 空类型列表
};template<typename... Types>
struct IsEmpty<TypeList<Types...>> {static const bool value = false; // 非空类型列表
};
7. 根据索引号查找typelist的某个元素(find)
此操作通过索引查找 typelist
中的特定类型。它使用递归进行索引减小,直到找到目标索引的类型。这使得可以根据位置快速访问特定类型。
template<typename TList, size_t Index>
struct Find;template<typename Head, typename... Tail>
struct Find<TypeList<Head, Tail...>, 0> {using type = Head; // 找到第一个元素
};template<typename Head, typename... Tail, size_t Index>
struct Find<TypeList<Head, Tail...>, Index> {using type = typename Find<TypeList<Tail...>, Index - 1>::type; // 递归查找下一个元素
};
8. 遍历typelist找到sizeof值最大的元素(get_maxsize_type)
该操作遍历 typelist
中的所有类型,并返回 sizeof
值最大的类型。它利用条件选择,递归比较每个类型的大小,确定最大值。这在需要根据类型大小进行处理时非常有用。
template<typename TList>
struct GetMaxSizeType;template<typename Head, typename... Tail>
struct GetMaxSizeType<TypeList<Head, Tail...>> {using type = typename std::conditional<(sizeof(Head) >= sizeof(typename GetMaxSizeType<TypeList<Tail...>>::type)),Head,typename GetMaxSizeType<TypeList<Tail...>>::type>::type; // 使用 std::conditional 比较
};// 特化版本,处理空类型列表
template<>
struct GetMaxSizeType<EmptyTypeList> {using type = void; // 空类型列表没有最大类型
};
完整代码
#include <iostream>
#include <type_traits>template<typename... Types>
struct TypeList {};using EmptyTypeList = TypeList<>;// 取得第一个元素
template<typename TList>
struct Front;template<typename Head, typename... Tail>
struct Front<TypeList<Head, Tail...>> {using type = Head;
};// 取得元素数量
template<typename TList>
struct Size;template<typename... Types>
struct Size<TypeList<Types...>> {static const size_t value = sizeof...(Types);
};// 移除第一个元素
template<typename TList>
struct PopFront;template<typename Head, typename... Tail>
struct PopFront<TypeList<Head, Tail...>> {using type = TypeList<Tail...>;
};// 向开头插入一个元素
template<typename TList, typename NewType>
struct PushFront;template<typename... Types, typename NewType>
struct PushFront<TypeList<Types...>, NewType> {using type = TypeList<NewType, Types...>;
};// 向结尾插入一个元素
template<typename TList, typename NewType>
struct PushBack;template<typename... Types, typename NewType>
struct PushBack<TypeList<Types...>, NewType> {using type = TypeList<Types..., NewType>;
};// 替换开头元素
template<typename TList, typename NewType>
struct ReplaceFront;template<typename... Tail, typename NewType>
struct ReplaceFront<TypeList<Tail...>, NewType> {using type = TypeList<NewType, Tail...>;
};// 判断是否为空
template<typename TList>
struct IsEmpty;template<>
struct IsEmpty<EmptyTypeList> {static const bool value = true;
};template<typename... Types>
struct IsEmpty<TypeList<Types...>> {static const bool value = false;
};// 根据索引查找元素
template<typename TList, size_t Index>
struct Find;template<typename Head, typename... Tail>
struct Find<TypeList<Head, Tail...>, 0> {using type = Head; // 找到第一个元素
};template<typename Head, typename... Tail, size_t Index>
struct Find<TypeList<Head, Tail...>, Index> {using type = typename Find<TypeList<Tail...>, Index - 1>::type; // 递归查找下一个元素
};// 遍历找到最大 sizeof 的类型
template<typename TList>
struct GetMaxSizeType;template<typename Head, typename... Tail>
struct GetMaxSizeType<TypeList<Head, Tail...>> {using type = typename std::conditional<(sizeof(Head) >= sizeof(typename GetMaxSizeType<TypeList<Tail...>>::type)),Head,typename GetMaxSizeType<TypeList<Tail...>>::type>::type; // 使用 std::conditional 比较
};// 特化版本,处理空类型列表
template<>
struct GetMaxSizeType<EmptyTypeList> {using type = void; // 空类型列表没有最大类型
};// 测试
int main() {using MyTypes = TypeList<int, double, char>;std::cout << "Size: " << Size<MyTypes>::value << std::endl; // 输出 3std::cout << "Is empty: " << IsEmpty<MyTypes>::value << std::endl; // 输出 0std::cout << "First element type: " << typeid(Front<MyTypes>::type).name() << std::endl; // 输出 intusing Popped = typename PopFront<MyTypes>::type;std::cout << "Size after pop: " << Size<Popped>::value << std::endl; // 输出 2using PushedFront = typename PushFront<MyTypes, float>::type;std::cout << "Size after push front: " << Size<PushedFront>::value << std::endl; // 输出 4using PushedBack = typename PushBack<MyTypes, long>::type;std::cout << "Size after push back: " << Size<PushedBack>::value << std::endl; // 输出 4using FoundType = typename Find<MyTypes, 1>::type; // 查找索引1的类型std::cout << "Found type at index 1: " << typeid(FoundType).name() << std::endl; // 输出 doubleusing MaxSizeType = typename GetMaxSizeType<MyTypes>::type; // 查找最大 sizeof 的类型std::cout << "Max size type: " << typeid(MaxSizeType).name() << std::endl; // 输出 doublereturn 0;
}
- TypeList: 用于存储类型的模板类。
- 基本操作: 提供了如获取第一个元素、计算大小、移除元素、插入元素、替换元素和判断是否为空等基本操作。
Find
: 通过递归查找指定索引的类型。GetMaxSizeType
: 通过比较各类型的sizeof
值,找出最大类型。- 使用示例: 在
main
函数中演示了如何使用这些操作。
5. tuple 实现
基础知识
1. 左值、右值、左值引用、右值引用
-
左值和右值:
- 左值 (lvalue): 表示一个可以被取地址的对象,具有持久的内存位置。例子:
int i = 10;
这里的i
是左值。 - 右值 (rvalue): 表示一个临时的对象,通常是不能取地址的,存在于表达式的右边。例子:
10
是右值。
- 左值 (lvalue): 表示一个可以被取地址的对象,具有持久的内存位置。例子:
-
左值引用:
- 通过左值引用 (
&
) 可以引用一个左值。例子:int &j = i; // j 是左值引用
- 左值引用只能绑定到左值上。尝试将右值绑定到左值引用会导致编译错误,但
const
左值引用可以绑定到右值:const int &j = 10; // 合法
- 通过左值引用 (
-
右值引用:
- 右值引用使用
&&
进行声明,允许绑定到右值。 - 例如:
int &&k = 10; // k 是右值引用
- 右值引用只能绑定到右值。尝试将左值绑定到右值引用会导致编译错误。
- 右值引用使用
-
普通变量:
- 普通的变量(如
int m;
)既不是左值引用也不是右值引用,因为引用必须带有&
或&&
修饰符。
- 普通的变量(如
2. std::move 究竟做了什么
-
std::move
是一个标准库函数,它将左值转换为右值,从而允许使用右值引用。例如:int &&k = std::move(i); // 将左值 i 转换为右值
-
重要的是,
std::move
不会执行任何移动操作,它只是一种类型转换,标记一个对象可以被“移动”。
3. std::forward 究竟做了什么
-
std::forward
是用于实现完美转发的工具,它允许保持参数的值类别(lvalue 或 rvalue)。在模板中使用时,可以根据传入的参数类型决定是保持为左值还是右值。template<typename T> void func(T&& arg) {// 完美转发process(std::forward<T>(arg)); }
4. 万能引用(转发引用)
- 万能引用是指在模板参数中使用的引用类型,可以绑定到左值或右值(例如
T&&
,其中 T 是模板参数)。这种引用在模板中被称为转发引用。
5. 完美转发
- 完美转发使得函数可以根据实际传入的参数类型选择合适的引用类型,从而避免不必要的复制和保证性能。例如,结合
std::forward
和万能引用,可以实现完美转发。
tuple 实现示例
C++ 标准库中的 std::tuple
是一个可以存储不同类型的元素的容器,以下是一个简单的自定义 tuple
实现示例:
tuple
是一种灵活的数据结构,能够存储不同类型的元素。理解左值、右值及其引用非常重要,因为tuple
的实现涉及到对象的生命周期管理、内存效率以及函数调用方式(如移动语义和转发)。std::move
和std::forward
是实现高效代码的重要工具,特别是在模板编程和泛型编程中。
#include <iostream>
#include <utility>
#include <type_traits>template<typename... Types>
class MyTuple;// 特化基础情况
template<>
class MyTuple<> {};// 递归定义
template<typename Head, typename... Tail>
class MyTuple<Head, Tail...> : private MyTuple<Tail...> {
public:Head head; // 当前元素using MyTuple<Tail...>::head; // 继承下一层的头部元素MyTuple(Head h, Tail... t): head(h), MyTuple<Tail...>(t...) {} // 构造函数
};// 获取元素
template<size_t Index, typename Tuple>
struct TupleElement;template<typename Head, typename... Tail>
struct TupleElement<0, MyTuple<Head, Tail...>> {using type = Head; // 返回当前头部元素
};template<size_t Index, typename Head, typename... Tail>
struct TupleElement<Index, MyTuple<Head, Tail...>> {using type = typename TupleElement<Index - 1, MyTuple<Tail...>>::type; // 递归获取
};// 获取元素的辅助函数
template<size_t Index, typename... Types>
typename TupleElement<Index, MyTuple<Types...>>::type& get(MyTuple<Types...>& tuple) {return static_cast<typename TupleElement<Index, MyTuple<Types...>>::type&>(tuple);
}int main() {MyTuple<int, double, char> myTuple(1, 2.5, 'c');std::cout << "First element: " << get<0>(myTuple) << std::endl; // 输出 1std::cout << "Second element: " << get<1>(myTuple) << std::endl; // 输出 2.5std::cout << "Third element: " << get<2>(myTuple) << std::endl; // 输出 creturn 0;
}
相关文章:
C++ 元编程
目录 C 元编程1. 术语2. 元函数1. 数值元函数示例:阶乘计算 2. 类型元函数示例:类型选择 3. 混合编程1. 常规的计算点积范例2. 混合元编程计算点积 4. typelist实现设计和基本操作接口(算法)完整代码 5. tuple 实现基础知识1. 左值…...

运行npm install 时,卡在sill idealTree buildDeps没有反应
一直停留在sill idealTree buildDeps 解决方法 npm config set registry https://registry.npm.taobao.org 配置后用下面命令看是否配置成功 npm config get registry 如果配置还不好使 就执行下行的ssl npm set strict-ssl false 然后执行 npm install 成功执行...
swc 编译 es6为commonjs
如果直接写es6后运行node index.js 报错:SyntaxError: Cannot use import statement outside a module js 我们这里使用swc来将es6编译成CommonJS。 以后可以作为一个简单的框架模版使用。 安装 pnpm add swc/cli swc/core 配置.swcrc {"$schema": &q…...
#nginx配置案例
示例配置 1:反向代理 负载均衡 缓存控制 http {# 定义后端服务器池,用于负载均衡upstream backend_servers {server backend1.example.com weight3; # 权重为3server backend2.example.com weight1; # 权重为1server backend3.example.com backup; …...

STM32—I2C通信外设
1.I2C外设简介 STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担支持多主机模型(可变多主机)支持7位/10位地址模式(11110......)支持不同的通…...

Java-测试-Mockito 入门篇
之前很长一段时间我都认为测试就是使用SpringBootTest类似下面的写法: SpringBootTest class SysAuthServiceTest {AutowiredSysRoleAuthMapper sysRoleAuthMapper;Testpublic void test() {QueryWrapper<SysRoleAuth> queryWrapper new QueryWrapper<&g…...

【jupyter notebook】环境部署及pycharm连接虚拟机和本地两种方式
Python数据处理分析简介 Python作为当下最为流行的编程语言之一 可以独立完成数据分析的各种任务数据分析领域里有海量开源库机器学习/深度学习领域最热门的编程语言在爬虫,Web开发等领域均有应用 与Excel,PowerBI,Tableau等软件比较 Excel有…...

TypeScript异常处理
1.异常的概念 程序运行中意外发生的情况就成为异常 例子: //除法运算function chu(num1:number,num2:number){if(num20){//throw 抛出异常throw new Error(除数不能为零)}let num:numbernum1/num2console.log(num) }//程序出现异常后会停止运行// 捕获异常try{ /…...
go的学习笔记
中文标准库文档:https://studygolang.com/pkgdoc 第一段代码 所有代码的主文件都是main.go,下面的代码直接在项目里面创建main.go运行 package main // 声明文件所在的包,每个go文件必须有归属的包import "fmt" // 引入程序需要的包,为了使用包下的函数,比如Print…...
卷积和转置卷积的输出尺寸计算
卷积和转置卷积的输出尺寸计算 卷积 h是输出的高,h是输入的高,k_h是卷积核的高 w类似stride1 h h - k_h padding*2 1通用公式 stride1就是上面的公式 h (h - k_w 2*padding stride)//stride 一些常见的卷积 高宽不变的卷积:kernel…...

vue3+ts 使用amCharts展示地图,1.点击左侧国家,可以高亮并放大右侧地图对应的国家。 2.展示数据球。
效果图展示: 1.点击左侧国家,可以高亮并放大右侧地图对应的国家。 2.展示数据球。 下载依赖 yarn add amcharts/amcharts5其中,props.countryData的数据格式为 [{ “country”: “加拿大”, “code”: “CA”, “deviceCount”: 1 },{ “c…...

汽车无钥匙启动功能工作原理
移动管家无钥匙启动是一种科技化的汽车启动方式,它允许车主在不使用传统钥匙的情况下启动车辆。这种技术通过智能感应系统实现,车主只需携带智能钥匙,当靠近车辆时,车辆能够自动解锁并准备启动。启动车辆时,车主无…...
C++标准的一些特性记录:C++11的auto和decltype
文章目录 auto容器遍历配合lambda表达式decltype两者对引用类型的处理是相同的decltype保留const,而auto不会保留const在C++11中,引入了两个新的关键字,auto和decltype两个关键字,都是用于做类型推断。但是使用的场景有些区别。 auto 容器遍历 auto这个关键字,我个人在编…...

【Elasticsearch系列四】ELK Stack
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

【新手上路】衡石分析平台使用手册-认证方式
认证方式 用户登录衡石系统时,系统需要对输入的用户名和密码进行验证,保证系统的安全。衡石提供 CAS、SAML2、OAUTH2等多种单点登录认证方式。在 SSO 单点登录中,衡石是服务提供者 SP(Service Provider)为用户提供所…...

数字电路与逻辑设计-触发器功能测试及其应用
一、实验目的 1.验证基本RS、JK、D、T和T’触发器的逻辑功能及使用方法; 2.能进行触发器之间的相互转换; 3.学习触发器的一些应用。 二、实验原理 触发器具有两个能够自行保持的稳定状态,用以表示逻辑状…...
【网站架构部署与优化】web服务与http协议
文章目录 HTMLHTML 概述HTML 语法规则HTML 文件结构头标签中常用标签静态网页与动态网页1. 静态网页2. 动态网页3. 动态网页语言 HTTP协议概述主要的HTTP版本包括:HTTP方法GET与POST方法的比较 HTTP状态码分类及常见状态码HTTP常见状态码 HTTP 请求流程分析1. 请求报…...

【字符函数】strcpy函数(字符串复制函数)+strcat函数(字符串追加)+strcmp函数(字符串比较)【笔记】
1.复制函数--------------strcpy函数 函数使用 char*strcpy(char* destination, const char* source) strcpy函数用于拷贝字符串,即将一个字符串中的内容拷贝到另一个字符串中(会覆盖原字符串内容)。它的参数是两个指…...

codetop字符串刷题,刷穿地心!!不再畏惧!!暴打面试官!!
主要供自己回顾与复习,题源codetop标签字符串近半年,会不断更新 1.有效的括号字符串2.括号生成3.最长单词4.字符串转换整数(atoi)5.整数转罗马数字6.罗马数字转整数7.比较版本号8.最长公共前缀9.面试题17.15.最长单词10.验证IP地址11.面试题01.06.字符串…...

快速体验Linux发行版:DistroSea详解与操作指南
DistroSea 是一个功能强大的在线平台,允许用户在无需下载或安装的情况下,通过浏览器直接测试多种Linux和BSD发行版。该平台非常适合Linux爱好者、系统管理员和开发者,提供一个简便的方式来体验各种操作系统而无需影响本地设备。 为什么选择D…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...