当前位置: 首页 > news >正文

【c++】模板详解

目录

  • 泛型编程
  • 模板的使用
    • 函数模板
      • 函数模板的本质
      • 函数模板的实例化
        • 显式实例化
        • 隐式实例化
      • 函数模板的模板参数的匹配原则
    • 类模板
      • 类模板的本质
      • 类模板的实例化
  • 非类型模板参数
  • 模板特化
    • 函数模板特化
    • 类模板特化
      • 类模板全特化
      • 类模板偏特化(半特化)
  • 模板分离编译
  • typename与class的小区别

泛型编程

提到模板就不得不提泛型编程的概念,泛型编程即编写一段与类型无关的通用代码,使得各种类型的参数都可以复用这段代码,从而顺利偷懒,提升编程效率。举例来说,假如我想实现一个交换函数(swap),那么问题来了,我想让这个函数既可以交换int类型的,也能交换double类型的,怎么处理呢,我们其实可以使用函数重载,实现两个swap函数,一个参数类型是int,一个是double就行,到这里还算轻松,但倘若是三种类型呢,又或者是四种,五种甚至是任意一种,使用函数重载固然可行,但写起来会非常麻烦。这种时候就应该使用泛型编程的思想,利用模板写出一段与类型无关的交换函数的代码,从而做到任意一种类型都能使用这个交换函数。就像给出了一个模子,浇注什么材料就是什么材料的模型。

模板的使用

说了那么多,模板到底应该怎样去使用呢,c++中的模板分为函数模板和类模板,下面我来一一介绍。

函数模板

template<class T>
T func(T a, T b)
{return a + b;
}int main()
{int a = 0;int b = 1;std::cout << func(a, b);return 0;
}

这是函数模板的一个简单的使用展示,template<class T1, class T2, ……, class Tn>的作用是声明模板参数列表,模板参数可以申请任意多个(模板参数一般是莫种类型,当然还有特例,这里我们之后再说),声明完模板参数列表之后,其下方的函数(仅指下方这一个)或类会与具体类型解耦,编译器会根据实际调用时传入的类型,自动生成对应的代码。这时我们就可以使用之前声明过的模板参数替换某些变量的类型,使其可以随模板参数的变化而变化。

函数模板的本质

当时我们将一个函数变成函数模板时,这个函数模板就不再是个函数了,它代表了一个函数家族,它可以通过模板初始化成很多个函数,它本身并不是函数,而是像一张设计图纸,只有传入模板参数时才会初始化成对应的函数。初始化函数的工作从由我们一个个手写变成了编译器自动初始化,减少了我们人写的量,提升了编程效率。

函数模板的实例化

函数模板的实例化分为显式实例化和隐式实例化。

显式实例化

显示实例化即直接明确给出函数的模板参数实例化函数使用,具体如下,

template<class T>
T func(T a, T b)
{return a + b;
}int main()
{int a = 0;int b = 1;std::cout << func<int>(a, b);return 0;
}

我这里在函数模板的后面加上(模板函数声明时有几个模板参数,这里就给几个来初始化),表示显式实例化func传入模板参数为int,之后这个函数就变成了只能接受两个int类型参数的函数了,传入别的类型可能就会报错。这里说可能会报错的原因是编译器在匹配参数类型失败之后也是会尝试隐式类型转换的。

隐式实例化
template<class T>
T func(T a, T b)
{return a + b;
}int main()
{int a = 0;int b = 1;std::cout << func(a, b);return 0;
}

隐式实例化就和我最开始所给的例子一样,不用直接声明,而是根据传入的参数的类型来推导模板参数,给了两个int类型的参数,编译器就会根据这两个参数的类型推导出模板参数为int,自动完成初始化。但倘若向上面这个例子一样,函数模板中两个函数参数所用的是一个模板参数,此时我却传入了两个不同类型的参数,会怎么样呢?答案是一定会报错,而对于显式实例化,却是不一定能够会报错,为什么呢?因为显式实例化提前给明模板参数初始化好了,函数已经是一个确定的函数了, 此时给两个不同类型的变量,编译器会尝试隐式类型转换,是有概率只吃警告不报错的;而对于隐式实例化,面对两个变量时函数模板还处于未确定模板参数未实例化的状态,此时给两个类型不一样的参数,编译器无法推导出模板参数,也就无法实例化,所以直接就报错了,这也是隐式实例化要注意的点,要匹配函数模板的模板参数。在匹配了函数模板的模板参数的情况下,使用隐式实例化还是相对来说比较方便的。此外,使用隐式实例化还应该注意编译器仅靠参数能否推断出全部的模板参数从而完成函数的初始化。就像下面这样,

template<class T, class t>
int func(T a, T b)
{t x;return a + b;
}int main()
{int a = 0;int b = 1;std::cout << func(a, b);return 0;
}

尽管传了看起来正确的参数,但还是会报错,因为只靠传入的参数类型只能推断出模板参数T,但没法知道t,这里就只能用显式实例化了。其实这种写法并不常见,我们写函数模板一般都是给参数上模板,很少在里面的变量用模板参数,但还是应该了解。

函数模板的模板参数的匹配原则

int add(int a, int b)
{std::cout << "add(int a, int b)";return a + b;
}template<class T1, class T2>
T1 add(T1 a, T2 b)
{std::cout << "add(T1 a, T2 b)";return a + b;
}int main()
{int a = 0;int b = 1;add(a, b);return 0;
}

在讲解模板参数的匹配原则之前,我先抛出这样一段代码,请问代码的结果是什么?结果是add(int a, int b),在c++中当我们调用的函数有一个函数模板又有一个确定的函数时,编译器会优先考虑确定的函数,有现成的就先吃现成的,但那也是有前提的,就是在选择用现成的函数能行的情况下不选现成的而选函数模板生成也不会生成一个更好的结果,这种情况下会调用现成的。具体来说向上面所给的例子,给的参数都是int类型,完美与现成的函数匹配,这时就不需要用类模板,因为就算调用类模板,你最都也就只能生成一个都是int类型的参数的函数,不会有更好的结果了。那倘若是下面这种情况,

int add(int a, int b)
{std::cout << "add(int a, int b)";return a + b;
}template<class T1>
T1 add(T1 a, T1 b)
{std::cout << "add(T1 a, T2 b)";return a + b;
}int main()
{int a = 0;double b = 1;add(a, b);return 0;
}

这时两个参数一个是int类型,一个是double类型,编译器依然会优先考虑现成的,能不能调用呢?其实是可以的,编译器会使用隐式类型转换将double变成int传给函数,但我们要明白此时的现成函数虽然可以调用但已经不是最优选择了,倘若模板参数可以生成更匹配的最优解函数,就回去用函数模板了,那我们看看函数模板可不可以生成更优解呢?答案是不行的,这里只给了一个模板参数,要求两个参数的类型一致,两个变量的类型不一致,编译器无法推导模板参数,隐式实例化压根就不会成功,更不用说最优解了,所以这里的答案还是add(int a, int b)。那我们再看像下面这种情况,

int add(int a, int b)
{std::cout << "add(int a, int b)";return a + b;
}template<class T1, class T2>
T1 add(T1 a, T2 b)
{std::cout << "add(T1 a, T2 b)";return a + b;
}int main()
{int a = 0;double b = 0;add(a, b);return 0;
}

这里与上面的不同之处就是模板参数给了两个,也就是允许两个参数类型不同,那答案也就显而易见了,是add(T1 a, T2 b),在现成函数无法完美匹配的前提下模板函数又可以生成更优解,这时就会使用模板函数了。

类模板

template<class T>
struct jiunian
{jiunian(const T& x):_a(x){}T _a;
};int main()
{jiunian<std::string> a(std::string("hello world"));std::cout << a._a;return 0;
}

以上就是一个类模板的简单演示,学习过函数模板之后,对于类模板基本就是一看就会,使用template<class T1, class T2, ……, class Tn>声明模板参数列表,使其下方的函数(仅指下方这一个)或类与具体类型解耦,编译器会根据实际调用时传入的类型,自动生成对应的代码。

类模板的本质

与函数模板类似,类模板代表了一个类家族,它不再指一个类,而是一种设计图,传入不同的参数会生成不同的类。

类模板的实例化

类模板不像函数模板,没有隐式实例化和显式实例化之分,因为类没有参数,所以直接传参数实例化就行。

template<class T>
struct a
{T _a;
};int main()
{a<int> x;return 0;
}

非类型模板参数

前面笔者也说过,模板参数通常情况之下是类型,但是c++之后也是更新了特例,如下所示,

template<size_t N>
struct jiunian
{int _a[N] = {0};
};int main()
{jiunian<10> a;std::cout << a._a[9];return 0;
}

c++允许在模板参数中用一个常量作为模板的参数,在模板类(函数)中可以将其作为常量来使用,但只支持整形类型的常量(int,char等),其他的都不支持,其设计的目的很大部分是为了能在类中定义普通数组,因为普通数组只能用常量指定大小,也因此要注意倘若使用非类型模板参数必须确保代码编译时就能确定参数的值,即只能传常量而不能传变量来初始化非类型模板参数。

模板特化

我们在使用模板进行泛型编程时,有时会遇到对于特定的类型不能用模板来处理而需要单独拎出来处理的情况,这是我们就要使用模板特化。

函数模板特化

template<class T>
bool compare(T a, T b)
{return a < b;
}template<>
bool compare<int*>(int* a, int* b)
{return *a < *b;
}int main()
{int a = 1;int b = 2;int* _a = &a;int* _b = &b;std::cout << compare(_a, _b);return 0;
}

一个简单的函数特化的使用就如上所示,笔者对比较函数传入int类型指针时进行了特化,因为指针进行比较是没有意义的,地址在每次运行时都会变化,时大时小,所以对其进行特化,对于int类型指针先引用再比较。但是实际上以上的操作可以直接像之前一样写一个函数重载就行了,编译器会选择更合适的一个,所以函数特化用的其实不是特别的多。

类模板特化

template<class T>
struct compareruler
{bool operator()(const T& a, const T& b){std::cout << "compareruler" << std::endl;return a < b;}
};template<class T>
struct compareruler<T*>
{bool operator()(T* const& a, T* const& b){std::cout << "compareruler<T*>" << std::endl;return *a < *b;}
};int main()
{int a = 0;int b = 1;int* _a = &a;int* _b = &b;compareruler<int*>comp;std::cout << comp(_a, _b);return 0;
}

一个简单的函数特化的使用就如上所示,笔者对于用于比较的仿函数进行了类模板特化,使其对于所有的指针类参数都能先解引用再比较。细心的读者可能发现我这里的类模板特化与之前的不一样,template<>中有参数,这是因为我这里对类模板进行了偏特化,类模板的特化与函数不一样,分为全特化与偏特化,下面一一讲解。

类模板全特化

全特化就是对类模板中的全部参数都确定化,因为类模板中的全部参数都确定了,template<>也就不需要声明模板参数了,这也表示之前的函数模板特化都是全特化,函数模板特化也只支持全特化。类模板全特化具体使用起来就像下面这样,

template<class T>
struct compareruler
{bool operator()(const T& a, const T& b){std::cout << "compareruler" << std::endl;return a < b;}
};template<>
struct compareruler<int*>
{bool operator()(int* const& a, int* const& b){std::cout << "compareruler<int*>" << std::endl;return *a < *b;}
};int main()
{int a = 0;int b = 1;int* _a = &a;int* _b = &b;compareruler<int*>comp;std::cout << comp(_a, _b);return 0;
}

这里只针对int类型指针进行特化,使仿函数传入int类型指针时会先解引用再比较,此时的template<>就不需要写参数了。

类模板偏特化(半特化)

偏特化是针对模板参数进行进一步限制的特化版本,这个限制可以是对参数的一部分进行特化,就像下面这样,

template<class T1, class T2>
struct compareruler
{bool operator()(const T1& a, const T2& b){std::cout << "compareruler" << std::endl;return a < b;}
};template<class T1>
struct compareruler<T1, int>
{bool operator()(const T1& a, const int& b){std::cout << "compareruler<T1, int>" << std::endl;return a > b;}
};int main()
{int a = 0;int b = 1;compareruler<int, int>comp;std::cout << comp(a, b);return 0;
}

也可以是对参数进行进一步的限制,就像开头给的例子一样

template<class T>
struct compareruler
{bool operator()(const T& a, const T& b){std::cout << "compareruler" << std::endl;return a < b;}
};template<class T>
struct compareruler<T*>
{bool operator()(T* const& a, T* const& b){std::cout << "compareruler<T*>" << std::endl;return *a < *b;}
};int main()
{int a = 0;int b = 1;int* _a = &a;int* _b = &b;compareruler<int*>comp;std::cout << comp(_a, _b);return 0;
}

只要是没有完全将类模板确定下来,就算是偏特化,像下面这样既有部分参数特化也有参数进一步限制的,只要不是完全确定,就也算是偏特化。

template<class T1, class T2>
struct compareruler
{bool operator()(const T1& a, const T2& b){std::cout << "compareruler" << std::endl;return a < b;}
};template<class T1>
struct compareruler<T1*, int*>
{bool operator()(T1* const& a, int *const& b){std::cout << "compareruler<T1*, int*>" << std::endl;return *a < *b;}
};int main()
{int a = 0;int b = 1;int* _a = &a;int* _b = &b;compareruler<int*, int*>comp;std::cout << comp(_a, _b);return 0;
}

模板分离编译

这是我们日常写代码时要避免的一个坑,我们再实际编写c++项目时,时常会用到分离编译,即使用多个源文件完成项目,在使用模板时倘若出现函数声明和定义不在一个源文件中就会出现报错,就像下面这样,

//源文件1
template<class T>
void test(T a)
{std::cout << a;
}//源文件2
template<class T>
void test(T a);int main()
{int a = 0;test(a);return 0;
}

编译器会报链接错误,但声明和定义都有,这是为什么呢?因为在c++的代码编译过程中是先分别编译各个源文件中的代码然后将函数连接起来最后在运行的,虽然我们在源文件2显式传参实例化了函数模板,但因为和它同一个源文件的只是一个函数声明,没法实例化,只能等着链接阶段站是否有这个函数,而在真正有函数定义的源文件1却因为源文件分离编译的缘故无法实例化,这就使得test变成了只有声明没有定义的空头函数,链接时就会报链接错误。怎么处理呢?一种方法是直接将声明和定义放在一个源文件之中,另一种就是在函数定义的源文件中显式实例化它,具体如下,

//源文件1
template<class T>
void test(T a)
{std::cout << a;
}template
void test<int>(int a);//显式实例化//源文件2
template<class T>
void test(T a);int main()
{int a = 0;test(a);return 0;
}

template加显式实例化的函数就是强制让编译器将指定的函数模板显式实例化为指定的一份等着链接。

分离编译的情况在类模板中也会出现,比如类模板函数的声明定义分离,如果写在了两份文件中也会引发连接错误,就像下面这样,

//文件1
template<class T>
struct a
{void print(T x);
};int main()
{a<int> A;A.print(1);return 0;
}//文件2
template<class T>
void a<T>::print(T x)
{std::cout << x;
}

这时和函数模板一样,要么写在一份文件中,要么强制显式实例化。

//文件1
template<class T>
struct a
{void print(T x);
};int main()
{a<int> A;A.print(1);return 0;
}//文件2
template<class T>
void a<T>::print(T x)
{std::cout << x;
}template
class a<int>;

typename与class的小区别

笔者在之前模板类型参数声明时都是使用的class,其实声明模板类型参数还可以用typename,老实说其实声明模板类型参数时用typename更为贴切,typename翻译过来就是类型名,更贴切使用场景,但因为class字母数更少,很多人包括我都更喜欢使用class,在声明模板类型参数这个用途上,两者没有任何区别,但对于typename还有一个class无法替代的用法。在引用​​嵌套依赖类型时必须使用typename明确告诉编译器这是一个类型,什么意思呢?就像下面这样,

template<class T>
class a
{T::iterator a;
};

T::it a;前面若不加typename就会报错,因为这里的it具体类型依赖于T,所以叫​​嵌套依赖类型。为什么​​嵌套依赖类型不加typename就会报错呢?因为编译器无法正确识别这是个类型,为什么无法识别呢?因为T::it既可能是一种类型,也可能是一个静态成员变量。假如T是一个类,那it就有可能表示静态成员变量,编译器无法分清,所以就会报错。需要注意,只要这里的T是一个处于不确定状态的类型,也就是模板没有实例化,因为模板没有实例化,编译器就无法在代码中查找,无法查找就无法确定。T可以有各种形式,即使是像

std::vector<T>::iterator  a;

这种c++自己库中的容器的情况也不行,因为有模板参数,所以没有实例化,没有实例化就没有代码可以查找,编译器就无法确定。只要是确定的类型,像

std::vector<int>::iterator a;

这样就不用加(当然想加也能加,typename就是告诉编译器这是个类型),当然这时就要确保vector真有iterator这个类型了,不然编译器会直接检查出来,之前给一个不确定的类型加typename可以先把编译器糊弄过去,等到运行时模板实例化了才会找,找不到就是运行时的报错。

相关文章:

【c++】模板详解

目录 泛型编程模板的使用函数模板函数模板的本质函数模板的实例化显式实例化隐式实例化 函数模板的模板参数的匹配原则 类模板类模板的本质类模板的实例化 非类型模板参数模板特化函数模板特化类模板特化类模板全特化类模板偏特化&#xff08;半特化&#xff09; 模板分离编译t…...

【Linux】驱动开发方法

使用Petalinux学习驱动开发时的一些经验。 部分图片和经验来源于网络,若有侵权麻烦联系我删除,主要是做笔记的时候忘记写来源了,做完笔记很久才写博客。 专栏目录:记录自己的嵌入式学习之路-CSDN博客 目录 1 基础——字符设备驱动 1.1 分配设备号(驱动入口使用)…...

BUUCTF——禁止套娃

BUUCTF——禁止套娃 进入靶场 一个近乎空白的页面 看一下框架 没什么有用的信息&#xff0c;扫个目录吧 只扫出来给flag.php&#xff0c;但是0B&#xff0c;估计又是个空网站 拼接访问一下 果然又是什么都没有 没有突破口 githack找找看看也没有源码吧 <?php include …...

Spring MVC @RequestBody 注解怎么用?接收什么格式的数据?

RequestBody 注解的作用 RequestBody 将方法上的参数绑定到 HTTP 请求的 Body&#xff08;请求体&#xff09;的内容上。 当客户端发送一个包含数据的请求体&#xff08;通常在 POST, PUT, PATCH 请求中&#xff09;时&#xff0c;RequestBody 告诉 Spring MVC 读取这个请求体…...

线性DP(动态规划)

线性DP的概念&#xff08;视频&#xff09; 学习线性DP之前&#xff0c;请确保已经对递推有所了解。 一、概念 1、动态规划 不要去看网上的各种概念&#xff0c;什么无后效性&#xff0c;什么空间换时间&#xff0c;会越看越晕。从做题的角度去理解就好了&#xff0c;动态规划…...

Qt中实现工厂模式

在Qt中实现工厂模式可以通过多种方式&#xff0c;具体选择取决于需求和场景。以下是几种常见的实现方法&#xff1a; 1. 简单工厂模式通过一个工厂类根据参数创建不同对象。cppclass Shape {public: virtual void draw() 0; virtual ~Shape() default;};class Circle : publ…...

基于 Dify + vLLM插件 + Qwen3 构建问答机器人Docker版

前提条件 硬件要求&#xff1a; 推荐 NVIDIA GPU (至少 16GB 显存&#xff0c;Qwen3 可能需要更多) 至少 32GB 内存 足够的存储空间 (Qwen3 模型文件较大) 软件要求&#xff1a; Docker 和 Docker Compose Python 3.8 CUDA 和 cuDNN (与你的 GPU 兼容的版本) 安装步骤…...

【Linux】Linux应用开发小经验

基于Petalinux工具链的Linux应用开发小经验&#xff0c;未完待续... 部分图片和经验来源于网络&#xff0c;若有侵权麻烦联系我删除&#xff0c;主要是做笔记的时候忘记写来源了&#xff0c;做完笔记很久才写博客。 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录…...

第39课 绘制原理图——绘制命令在哪里?

绘制原理图符号的命令在哪里&#xff1f; 在新建完原理图之后&#xff0c;我们就可以在原理图上绘制各种相关的符号了。 我们基本会从以下的两个地方&#xff0c;找到绘制各种符号的命令&#xff1a; 菜单栏中的“放置”菜单&#xff1b; 悬浮于设计窗口中的快速工具条 在初…...

第十四篇:系统分析师第三遍——15章

目录 一、目标二、计划三、完成情况四、意外之喜(最少2点)1.计划内的明确认知和思想的提升标志2.计划外的具体事情提升内容和标志 五、总结六、后面准备怎么做&#xff1f; 一、目标 通过参加考试&#xff0c;训练学习能力&#xff0c;而非单纯以拿证为目的。 1.在复习过程中&…...

市面上所有大模型apikey获取指南(持续更新中)

阿里云(千问) 官方文档&#xff1a; 百炼控制台 1. 登录百炼控制台 2.前往我的api页面百炼控制台 3.创建api4. 添加描述&#xff08;用于aichat&#xff09; Deepseek 官方文档&#xff1a;首次调用 API | DeepSeek API Docs 1. 登录api平台 DeepSeek 开放平台 2. Deep…...

Java框架“若依RuoYi”前后端分离部署

运行环境 Eclipse IDE for Enterprise Java and Web Developers 下载Eclipse解压Eclipse到文件夹 Maven 下载Maven解压Maven到文件夹配置环境变量MAVEN_HOME为Maven安装位置配置环境变量path为%MAVEN_HOME%\bin Redis 下载Redis解压Redis到文件夹配置环境变量path为Redis安装位…...

计网_可靠传输ARQ机制

2024.09.04&#xff1a;网工老姜&beokayy网工学习笔记 第5节 可靠传输机制 5.1 可靠传输5.2 ARQ机制、ARQ协议5.3 ARQ简介&#xff08;可靠传输&#xff09;5.3.1 停止等待协议&#xff08;1&#xff09;无差错情况&#xff08;2&#xff09;有差错情况确认丢失确认迟到 5.…...

实验-组合电路设计1-全加器和加法器(数字逻辑)

目录 一、实验内容 二、实验步骤 2.1 全加器的设计 2.2 加法器的设计 三、调试过程 3.1 全加器调试过程 2.加法器的调试过程 四、实验使用环境 五、实验小结和思考 一、实验内容 a) 介绍 在这次实验中&#xff0c;你将熟悉 Logisim 的操作流程&#xff0c;并且学习…...

软件管理(安装方式)

1.rpm安装 1.1.rpm介绍 rpm软件包名称: 软件名称 版本号(主版本、次版本、修订号) 操作系统 -----90%的规律 举例:openssh-6.6.1p1-31.el7.x86_64.rpm 数字是版本号:第一位主版本号,第二位次版本号,带横杠的是修订号, el几---操作系统的版本。 #用rpm安装需要考虑如下信…...

工作记录 2015-07-15

工作记录 2015-07-15 序号 工作 相关人员 1 在CDAEditor上增加签名的处理&#xff0c;已经基本改完。明天整理说明文档&#xff0c;更新193服务器。 郝 需要改了签名的处理 增加了签名的按钮&#xff1a; 已经签名过的会有提示&#xff1a; 签名后PDF的预览如下&#xf…...

《算法导论(第4版)》阅读笔记:p4-p5

《算法导论(第4版)》学习第 3 天&#xff0c;p4-p5 总结&#xff0c;总计 2 页。 一、技术总结 1.instance Thus, given the input sequence h31; 41; 59; 26; 41; 58i, a correct sorting algorithm returns as output the sequence h26; 31; 41; 41; 58; 59i. Such an inp…...

【Mytais系列】Update语句执行流程

以下是通过 时序图 和 文字说明 详细描述的 MyBatis 执行 UPDATE/INSERT/DELETE 语句的完整流程&#xff0c;包括缓存清理、事务提交和数据库操作的各个环节&#xff1a; 时序图&#xff08;Sequence Diagram&#xff09; 详细执行流程解析 1. 客户端发起更新请求 客户端调用…...

LeetCode —— 145. 二叉树的后序遍历

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…...

Python函数参数机制深度解析与最佳实践

引言 在Python开发中&#xff0c;函数的参数机制是构建灵活、可维护代码的核心要素。本文将通过7个关键维度深入剖析函数参数的底层原理与高级用法&#xff0c;结合代码实例揭示参数传递的本质规律&#xff0c;助您掌握工业级函数设计技巧&#xff08;基于Python 3.12环境验证…...

ARM 算数指令

加法 ADD 减法 SUB 取负 NEG 比较 CMP 乘法 MUL 移位 LSL、LSR、ASL、ASR、ROL、ROR加法和减法 绝大多数微处理器都实现了带进位的加法指令&#xff0c;能够将两个操作数和条件码寄存器中的进位位加到一起。这条指令会使字长大于计算机固有字长的链接运算更加方便。 说明了如何…...

普通IT的股票交易成长史--20250502 突破(2)

声明&#xff1a;本文章的内容只是自己学习的总结&#xff0c;不构成投资建议。文中观点基本来自yt站方方土priceaction&#xff0c;综合自己的观点得出。感谢他们的无私分享。 送给自己的话&#xff1a; 仓位就是生命&#xff0c;绝对不能满仓&#xff01;&#xff01;&#…...

什么是 Redis?

什么是 Redis? Redis(全称是 Remote Dictionary Server,远程字典服务器)是一个非常快的开源内存数据库,它主要用来存储“键-值”对类型的数据。与传统的数据库不太一样,Redis的数据主要存放在内存中,所以它读写速度特别快。 通俗比喻: 想象你有一个小仓库,里面放了…...

IEEE LaTeX会议模板作者对齐、部门长名称换行

第二行作者对齐 参考链接&#xff1a; https://tex.stackexchange.com/questions/458204/ieeetran-document-class-how-to-align-five-authors-properly/458208#458208https://tex.stackexchange.com/questions/582487/how-to-align-four-author-names-in-the-ieee-conferenc…...

前端面经-VUE3篇(二)--vue3组件知识(二)依赖注入、异步组件、生命周期、组合式函数、插件

目录 一、依赖注入 1、 依赖注入是什么&#xff1f; 2、最基础的使用 3、为什么使用依赖注入&#xff1f; 4、 使用 Symbol 作注入名 二、异步组件 1、什么是异步组件&#xff1f; 2、最基础用法&#xff1a;defineAsyncComponent 3、在模板中使用异步组件 4、配置加载状态…...

Manus联合创始人:公司产品基于Claude和阿里千问大模型开发

3月11日消息&#xff0c;日前&#xff0c;Manus官方在社交平台转发了公司联合创始人、首席科学家季逸超对Manus的技术解读&#xff0c;季逸超在评论区回复网友关于“Manus使用了哪一个基础大模型”这一问题时回复称&#xff0c;“我们用过Claude&#xff0c;也用过不同版本的Qw…...

华为云Flexus+DeepSeek征文|快速搭建Dify LLM应用开发平台教程

目录 部署Dify-LLM应用开发平台开始使用一键卸载注意事项 部署Dify-LLM应用开发平台 1、首先需要访问快速搭建Dify-LLM应用开发平台-华为云 2、使用"一键部署"功能快速搭建Dify平台快速搭建Dify LLM应用开发平台-云社区-华为云&#xff0c;本文在这里选择一键部署&…...

简介QML中的Canvas

2025年5月3日&#xff0c;周六晚上 QML中的Canvas是一个强大的绘图组件&#xff0c;允许开发者通过JavaScript在界面上进行动态的2D图形绘制。它类似于HTML5的<canvas>元素&#xff0c;适用于实现自定义图形、动画、游戏开发以及图表绘制等场景。 核心特性 绘图能力 • …...

装饰器@wraps(func)详解

1. wraps(func) 的核心作用 wraps 是 Python 标准库 functools 提供的装饰器&#xff0c;用于保留被装饰函数的原始元信息。 它通过将原函数的 __name__、__doc__、__module__ 等属性复制到装饰器内部的包装函数中&#xff0c;避免装饰器对函数身份信息的“掩盖”。 2. 元信息…...

vue的diff算法是什么、比较方式,原理分析、示例解释讲解

Vue Diff算法概述 Vue 的 Diff 算法是一种高效的虚拟 DOM 更新机制&#xff0c;用于最小化真实 DOM 的操作开销。它通过比较新旧 Virtual DOM 树中的差异&#xff0c;仅更新那些实际发生改变的部分&#xff0c;从而提升性能。 定义 Diff 算法的核心目标是在 MVVM 开发模式下…...

Day04 新增套餐

###今天的任务主要是自主完成套餐管理的模块### 1.新增套餐 在前端页面接口中我们可以看到在新增套餐的时候需要选择添加到菜单中的菜品 因此我们需要设计一个接口可以通过根据分类id&#xff08;category_id&#xff09;来查询该分类下的菜品 1.1根据分类id查询分类下的菜…...

WEB前端小练习——记事本

一、登陆页面 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>记事本登录注册</title><link…...

在多线程环境下如何设计共享数据结构保证原子操作与数据一致性

在多线程环境下如何设计共享数据结构保证原子操作与数据一致性 1. 引言 在现代软件开发中,多线程编程是提升程序性能和响应速度的重要手段。然而,多线程环境下的 共享数据管理 极具挑战性,若处理不当,可能引发 竞争条件(Race Conditions)、数据不一致(Data Inconsiste…...

洛谷 P1850 [NOIP 2016 提高组] 换教室

题目传送门 前言 终于自己想出概率期望 d p dp dp 的状态了&#xff0c;但是依旧没能相对转移方程。&#xff08;招笑&#xff09; 暴力 这题部分分和特殊情况分给的挺多的&#xff0c;所以先拿部分分。 一、思路 先跑一边 F l o y d Floyd Floyd 最短路求出两点间最短距…...

1penl配置

好的&#xff0c;根据您提供的 1pctl 命令输出信息&#xff0c;我们来重新依次回答您的所有问题&#xff1a; 第一&#xff1a;1Panel 怎么设置 IP 地址&#xff1f; 根据您提供的 user-info 输出&#xff1a; 面板地址: http://$LOCAL_IP:34523/93d8d2d705 这里的 $LOCAL_I…...

Windows下调试WebRTC源码

一、引言 《Windows下编译WebRTC源码》讲述了Windows下编译WebRTC源码的方法。本文在其基础之上&#xff0c;讲述使用Visual Studio调试WebRTC源码的方法。 二、生成Visual Studio工程文件 按照 《Windows下编译WebRTC源码》编译出webrtc.lib 后&#xff0c;执行下面的命令生…...

基于大模型的肾结石诊疗全流程风险预测与方案制定研究报告

目录 一、引言 1.1 研究背景与意义 1.2 国内外研究现状 1.3 研究目标与内容 二、大模型技术原理与应用概述 2.1 大模型的基本原理 2.2 大模型在医疗领域的应用进展 2.3 适用于肾结石预测的大模型选择与依据 三、术前风险预测与准备 3.1 患者身体状况评估 3.2 结石情…...

《ATPL地面培训教材13:飞行原理》——第5章:升力

翻译&#xff1a;刘远贺&#xff1b;工具&#xff1a;Cursor & Claude 3.7&#xff1b;过程稿 第5章&#xff1a;升力 目录 空气动力系数基本升力方程回顾升力曲线升力曲线的解释速度-动压关系密度高度翼型剖面升力特性阻力特性简介升阻比飞机重量对最小飞行速度的影响表…...

STM32部分:2、环境搭建

飞书文档https://x509p6c8to.feishu.cn/wiki/DQsBw76bCiWaO4kS8TXcWDs0nAh Keil MDK用于编写代码&#xff0c;编译代码芯片支持包&#xff0c;用于支持某类芯片编程支持STM32CubeMX用于自动生成工程&#xff0c;减少手动重复工作 STM32F1系列芯片支持包 软件下载 直接下载&am…...

STL之list容器

list的介绍 1.list的底层是双向链表结构&#xff0c;双向链表中的每个元素在互不相关的独立结点中&#xff0c;在结点中通过指针指向前一个元素和后一个元素 2.list是可以在常数范围内在任意位置的插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代 3.vector的…...

DNS 域名解析

DNS&#xff08;Domain Name System&#xff09; 是一个将域名转换为IP地址的系统。它的主要功能是使用户能够通过易于记忆的域名访问互联网资源&#xff0c;而不是记住复杂的IP地址。DNS类似于“互联网的电话簿”&#xff0c;帮助计算机找到彼此的位置。 一、DNS的基本概念 …...

我写了一个分析 Linux 平台打开文件描述符跨进程传递的工具

Linux 系统的设计中&#xff0c;继承了 Unix “一切皆文件” (Everything is a file) 的思想&#xff0c;系统中的众多对象&#xff0c;都可以表示为文件&#xff0c;可以对它们执行文件操作&#xff0c;如 read()、write()、mmap()、ioctl()、close() 和 poll() 等。Linux 系统…...

QML图像提供器 (Image Provider)

QML 中的图像提供器是一种自定义图像加载机制&#xff0c;允许你从非文件源&#xff08;如数据库、网络或程序生成的内容&#xff09;提供图像数据。 主要类型 QQuickImageProvider - 基础图像提供器 QPixmapImageProvider - 提供 QPixmap 图像 QImageImageProvider - 提供 …...

【Java学习】通配符?

面向对象系列八&#xff1a;泛型(二) 一、通配符? 二、泛型符<> 1.泛型类里 2.泛型类外 2.1使用过程中 2.2使用最后末 三、限制 1.泛型类里的限制 2.延申处的限制 2.1extend限制上界 2.1.1返回值接 2.1.2形参传 2.2super限制下界 2.2.1形参传 2.2.2返回值…...

安卓基础(悬浮窗和摄像)

ACTION_MANAGE_OVERLAY_PERMISSION​​ 的作用就是 ​​打开系统设置的「悬浮窗权限管理页面」 Intent intent new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" getPackageName()) ); startActivity(intent); 直接跳转目标应用的权限…...

一种实波束前视扫描雷达目标二维定位方法——论文阅读

一种实波束前视扫描雷达目标二维定位方法 1. 专利的研究目标与实际问题意义2. 专利提出的新方法、模型与公式2.1 运动平台几何建模与回波信号构建2.1.1 距离历史建模2.1.2 回波信号模型2.2 距离向运动补偿技术2.2.1 匹配滤波与距离压缩2.3 加权最小二乘目标函数2.3.1 方位向信号…...

基于springboot的金院银行厅预约系统的设计及实现(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;信息管理系统的实施在技术上已逐步成熟。信息管理系统是一个不断发展的新型学科&#xff0c;任何一个单位要生存要发展&#xff0c;要高效率地把内部活动有机地组织起来&#xff0c;就必须建立与自身特点相适应的…...

AVFormatContext 再分析零

随着对于AVFormatContext 各个参数的学习&#xff0c;逐渐可以从 整体架构上 再认识一下 AVFormatContext 了。 还是从解封装的第一步开始。 int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options); 实际上…...

【学习心得】魔塔(ModelScope)和抱抱脸(Hugging Face)下载模型小细节

介绍常用的两种在模型社区如魔塔&#xff08;ModelScope&#xff09;和抱抱脸&#xff08;Hugging Face&#xff09;&#xff0c;下载预训练模型的方法&#xff0c;然后说明各种方法里面的小细节。 一、SDK下载 对于希望直接通过编程方式集成模型下载功能到自己的项目中的开发…...

嵌入式硬件篇---STM32 系列单片机型号命名规则

文章目录 前言一、STM32 型号命名规则二、具体型号解析1. STM32F103C8T6F103:C:8:T6:典型应用2. STM32F103RCT6F103:R:C:T6:典型应用三、命名规则扩展1. 引脚数与封装代码2. Flash 容量代码3. 温度范围代码四、快速识别技巧性能定位:F1/F4后缀差异硬件设计参考:引脚数…...