11 类型泛化
11 类型泛化
- 1、函数模版
- 1.1 前言
- 1.2 函数模版
- 1.3 隐式推断类型实参
- 1.4 函数模板重载
- 1.5 函数模板类型形参的默认类型(C++11标准)
- 2、类模版
- 2.1 类模板的成员函数延迟实例化
- 2.2 类模板的静态成员
- 2.3 类模板的递归实例化
- 2.4 类模板类型形参缺省值
- 3、类模板的扩展
- 3.1 模板型成员变量
- 3.2 模板型成员函数
- 3.3 模板型成员类型
- 3.4 类模板中成员虚函数
- 4、模板的特殊用法
- 4.1 数值型的类型形参
- 4.2 模板型的类型形参
- 5、模板的经典错误(补)
- 5.1 模板二次编译
- 5.2 嵌套依赖
- 5.3 利用类型形参调用成员函数模板
- 5.4 子类模板访问基类模板
1、函数模版
1.1 前言
首先C++为强类型语言
-优点:有很多的数据类型(基本类型、类类型)在类型安全性方面是无可比拟的
-缺点:因为数据类型的多样性,在很大程度上会给程序员编写通用代码带来麻烦
这就使得程序员需要为每一种数据类型编写完全相同或者近乎完全相同的代码,即便它们在抽象层面是一致的。
int Max(int x, int y){return x > y ? x : y;
}
double Max(double x, double y){return x > y ? x : y;
}string Max(string x, string y){return x > y ? x : y;
}
int main(){int nx = 10, ny = 11;cout << Max(nx, ny) << endl;double dx = 1.0, dy = 1.1;cout << Max(dx, dy) << endl;string sx = "1.0", sy = "1.1";cout << Max(sx, sy) << endl;...如果有其他类型的比较大小,我们需要为每一种类型编写相同的代码
}
1.2 函数模版
- 定义语法:
template<class|typename 类型形参1,class|typename类型形参2,...>返回值类型 函数模板名(调用形参1,调用形参2,…){...}示例:
template<typename T>T Max(T x,Ty){return x y?x:y;
}
注意:可以使用任何标识符作为类型形参的名称,但使用“T”己经称为一种惯例,“T”表示的是,调用者在使用函数模板时指定的任意类型
- 使用:使用函数模板必须对函数模板进行实例化
- 语法
函数模板名<类型实参1,类型实参2,>(调用实参1…);
- 示例
// 定义函数模板
template<typename T>T Min(T x, T y){return x > y ? y : x;
}int main(){int nx = 10, ny = 11;// 使用函数模板cout << Min<int>(nx, ny) << endl;double dx = 1.0, dy = 1.1;cout << Min<double>(dx, dy) << endl;string sx = "1.0", sy = "1.1";cout << Min<string>(sx, sy) << endl;return 0;
}
- 分析
- 编译器并没有把函数模板翻译成一个可以处理任何数据类型的单一实体
- 编译器在实例化函数模板时根据类型实参从函数模板中产生一个真正的函数实体
- 函数模板并不是一个函数实体,通过实例化才能产生真正的函数实体
- 函数模板可以看成是编译器生成函数实体的一个依据而已
- 这种用具体数据类型替换函数模板类型形参的过程叫做实例化,这个过程将产生一个函数模板的实例(函数实体)
- 原则上来说可以使用任何类型来实例化函数模板,不管其为基本类型还是类类型但前提是这个类型必须支持函数模板所要执行的操作
1.3 隐式推断类型实参
- 概念
- 若函数模板的调用形参和类型形参相关,那么在实例化函数模板时即使不显式指明类型实参,编译器也有能力根据调用实参的类型隐式推断出类型实参的类型
- 获得和调用普通函数一致的书写形式
template<typename T>T Min(T x, T y){return x > y ? y : x;
}
int main(){int nx = 10, ny = 11;// 调用形参和类型形参相关cout << Min(nx, ny) << endl;// --> cout << Min<int>(nx, ny) << endl;double dx = 1.0, dy = 1.1;cout << Min(dx, dy) << endl;string sx = "1.0", sy = "1.1";cout << Min(sx, sy) << endl;return 0;
}
- 三种情况不能做隐式推断
1: 调用参数和类型参数不完全相关
template <typename T, typename D>void Foo(D x){cout << x << endl;
}
int main(){int nx = 10, ny = 11;//Foo(nx);// 不能推断出T的类型Foo<float>(nx);return 0;
}
2: 隐式推断类型实参不能同时隐式类型转换
template <typename T>void Foo1(T x,T y){cout << x << endl;
}
int main(){// Foo1(11,13.5);// 隐式推断类型实参不能同时隐式类型转换Foo1(11, (int)13.5);return 0;
}
3: 返回值类型不能隐式推断
template<typename R,typename T>
R Bar(T x){R r;return t;
}
// 返回值类型不能隐式推断
void C11_06(){int a = 10;//Bar(10);// 根据实参能推断出形参T的类型,但是无法推断出R的类型Bar<float>(10);
}
1.4 函数模板重载
- 普通函数和能够实例化出该函数的函数模板构成重载关系
- 在调用参数类型匹配度相同情况下编译器优先选择普通函数
- 除非函数模板可以产生调用参数类型匹配度更好的函数
- 隐式推断类型实参不能同时隐式类型转换但普通函数可以,如果在传递参数时如果需要编译器做隐式类型转换,则编译器选择普通函数。
- 可以在实例化时用<>强行通知编译器选择函数模板。
void MaxType(int x, int y){cout <<"1.MaxType" << endl;
}
template<typename T>void MaxType(T x, T y){cout << "2.MaxType" << endl;
}int main(){int nx = 10, ny = 11;MaxType(nx,ny); // 调用普通函数 在调用参数类型匹配度相同情况下编译器优先选择普通函数double dx = 1.0, dy = 1.1;MaxType(dx, dy);// 调用函数模版 函数模板可以产生调用参数类型匹配度更好的函数MaxType(nx,dy);// 调用函数模版 隐式推断类型实参不能同时隐式类型转换但普通函数可以MaxType<>(nx, ny);// <>强行通知编译器选择函数模板。return 0;
}
1.5 函数模板类型形参的默认类型(C++11标准)
- 函数模板的类型形参可以带有默认类型
- 在实例化函数模板时,如果提供了类型实参则用所提供的类型实参来实例化函数模板
- 在实例化函数模板时,如果没提供类型实参则用类型形参的缺省类型来实例化函数模板
- 如果某一个类型形参带有缺省类型,则其后的类型形参都必须带有缺省类型
template <typename T=short, typename D=float>void Foo2(int x=0){T t;D d;cout << "t的类型" << typeid(t).name() << " d的类型" << typeid(d).name() << endl;
}
int main(){Foo2<int, double>(100);// 用提供的类型Foo2(100);// 用默认类型return 0;
}
2、类模版
- 形式:
// 书写
template<tyepname类型形参1,...>
class 类模板名{...
}
// 示例
template<typename A,typename B>
class CMath{
public:A m a;B func0{…}
}
- 使用:类模板必须对类模板进行实例化(产生真正的类)
- 类模板本身并不代表一个确定的类型(即不能用于定义对象)
- 只有通过类型实参实例化成真正的类后才具备类的特性(即可以定义对象)。
template<typename T>
class CMath{
public:CMath(T t1, T t2) :m_t1(t1), m_t2(t2){}T add(){ return m_t1 + m_t2; }T sub();// 声明
private:T m_t1;T m_t2;
};
// T sub()定义 template<typename T>不能丢,要用类名引成员,切记不用要类模板引成员
template<typename T>
T CMath<T>::sub(){return m_t1 - m_t2;
}int main(){int nx = 10, ny = 11;CMath<int>m1(nx, ny);cout << m1.add() << endl;double dx = 1.0, dy = 1.1;CMath<double>m2(dx, dy);cout << m2.add() << endl;string sx = "1.0", sy = "1.1";CMath<string>m3(sx, sy);cout << m3.add() << endl;return 0;
}
2.1 类模板的成员函数延迟实例化
类模板被实例化产生真正类的一刻,类模板中的成员函数并没有实例化, 成员函数只有在被调用时才会被实例化(即产生真正成员函数),称之为成员函数的延迟实例化
注意:成员虚函数除外
某些类型虽然并没有提供类模板所需要的全部功能,但照样可以用它来实例化类模板,只要不调用那些未提供功能的成员函数即可。
int main(){// CMath<int> 编译到这是,类中只有成员变量,没有成员函数// CMath<int>m1(nx,ny) // 此时编译器才会给类中添加构造函数// m1.add() // 此时才会去类中添加add的成员函数return 0;
}
2.2 类模板的静态成员
- 类模板中的静态成员既不是每个对象拥有一份也不是类模板拥有一份,应该是由类模板实例化出的每一个真正的类各自拥有一份,且为该实例化类定义的所有对象共享
template <typename T> class A
{
public:static T m_t;// 声明static void foo(){cout << "A<T>::foo()" << endl;}
};
template <typename T> T A <T> ::m_t=T();// 定义 T()零值初始化
// 类模板中的静态成员即不是每个对象拥有一份也不是类模板拥有一份,
// 应该是由类模板实例化出的每一个真正的类各自拥有一份,且为该实例化类定义的所有对象共享
int main(){A<int> x, y;cout << "&A<int>::m_t:" << &A<int>::m_t << endl; // &A<int>::m_t:00DB53F8cout << "&x.m_t:" << &x.m_t << " &y.m_t:" << &y.m_t << endl; //&x.m_t:00DB53F8 &y.m_t:00DB53F8A<double> m, n;cout << "&A<double>::m_t:" << &A<double>::m_t << endl; // &A<double>::m_t:00DB5400cout << "&m.m_t:" << &m.m_t << " &m.m_t:" << &m.m_t << endl;// &m.m_t:00DB5400 &m.m_t:00DB5400return 0;
}
2.3 类模板的递归实例化
- 概念
- 利用类模板实例化产生的类来实例化类模板自身,这种做法称之为类模板的递归实例化
- 应用
- 通过这种方法可以构建空间上具有递归特性的数据结构
(例如:多维数组)
- 通过这种方法可以构建空间上具有递归特性的数据结构
- 示例
- Array<Array<int> >
template<typename T>class Array{
public:T& operator[](size_t i){return arr[i];}
private:T arr[10];
};
# include <iomanip>
int main(){Array<int> a; // a对象当成是一维数组看待for (int i = 0; i < 10; i++){a[i] = 1000 + i;}for (int i = 0; i < 10; i++){cout << a[i] << " ";}cout << endl;Array< Array<int> > b; // 类模板的递归实例化for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){b[i][j] = i*j;}}for (int i = 1; i < 10; i++){for (int j = 1; j <= i; j++){cout << i << "X" << j << "=";cout << left << setw(2) << setfill(' ') << b[i][j] << " ";}cout << endl;}return 0;
}
2.4 类模板类型形参缺省值
- 类模板的类型形参可以带有缺省类型
- 在实例化类模板时,如果提供了类型实参则用所提供的类型实参来实例化类模板
- 在实例化类模板时,如果没提供类型实参则用类型形参的缺省类型来实例化类模板
- 如果某一个类型形参带有缺省类型,则其后的类型形参都必须带有缺省类型
template<typename T=short,typename D=int>
class CCMath{
private:T m_t;D m_d;
public:void print(){cout << "m_t的类型:" << typeid(m_t).name() << endl;cout << "m_d的类型:" << typeid(m_d).name() << endl;}
};int main(){CCMath<>m1;CCMath<int>m2;CCMath<int,double>m3;m1.print();m2.print();m3.print();return 0;
}
3、类模板的扩展
3.1 模板型成员变量
成员变量,但其类型是由类模板实例化的未知类,称之为模板型成员变量
- 示例
template <typename T> class Array{...}
template <typename D> class Sum{
public :Array<D> m_d; // 模板型成员变量
}
template<typename T>class Array2{
public:T& operator[](size_t i){return arr[i];}
private:T arr[10];
};
template<typename D>class Sum{
public:Sum(const Array2<D>& v) :m_a(v){}D add(){ // 求和器D d = D();for (int i = 0; i < 10; i++){d += m_a[i];}return d;}
private:Array2<D> m_a;//模板型成员变量
};int main(){Array2<int> a;for (int i = 0; i < 10; i++){a[i] = i+1;}Sum<int> s(a);cout << s.add() << endl;return 0;
}
3.2 模板型成员函数
模板型成员函数 又名 成员函数模板
示例:
template<typename T> class BB{
public:template<typename D>void foo(){ // 成员函数模板cout << "AA::foo<D>" << endl;}template<typename D>void bar();// 声明
};
template<typename T> template<typename D> void BB<T>::bar(){// 定义cout << "BB :: bar" << endl;
};void C11_15(){AA a;a.foo<int>();BB<int>b; // 对类模板实例化b.foo<int>();// 对函数模板实例化b.bar<int>();
}
3.3 模板型成员类型
template<typename X>class A1{
public:template<typename Y>class B1{public:template<typename X> void foo(){ // 模板型成员类型cout << "foo() " << endl;}};
};
int main(){A1<int>::B1<int>b;b.foo<int>();return 0;
}
3.4 类模板中成员虚函数
template <typename T> class Base{
public:virtual void foo(){//虚函数cout << "Base<T>::foo" << endl;}
};
// 只有在父子类中,才可以将模板进行合并
template<typename T, typename D>class Derived :public Base<T>{
public:void foo(){cout << "Derived<T,D>::foo" << endl;}
};
int main(){Derived<int, double> dr;Base<int>* pdase = &dr;pdase->foo();return 0;
}
注意:类模板中可以有虚函数,也可以表现出多态性,但是不能有成员虚函数模板
这是因为根据成员虚函数的多态机制,需要一个虚函数表(表中保存成员虚函数的入口地址),而这个表是编译器在实例化类模板时就创建,而成员函数模板的实例化(即产生真正的函数实体)需要编译器处理完并且调用后才会完成,这时才出现成员虚函数的地址,所以成员函数模板的延迟实例化,阻碍了虚函数表的构建
4、模板的特殊用法
4.1 数值型的类型形参
模板的类型形参也可以是数值类型(只能是整数),可以有缺省值
template<typename T,int S=10>class Array{
public:T& operator[](size_t i){return arr[i];}int size(){return S;}
private:T arr[S];
};
int main(){Array<int, 30> a;for (int i = 0; i < a.size(); i++){a[i] = 1000 + i;}for (int i = 0; i < a.size(); i++){cout << a[i] << ' ';}return 0;
}
4.2 模板型的类型形参
模板的类型形参也可以是类模版,可以有缺省值
template<typename T>class Array{
public:T& operator[](size_t i){return arr[i];}int size(){return 10;}
private:T arr[10];
};
template<typename D, template<typename M> class C = Array> class SumArray{
public:SumArray(const C<D>& v) :m_a(v){};D add(){D a = D();for (int i = 0; i < m_a.size(); i++){a += m_a[i];}return a;}
private:C<D> m_a;
};
int main(){Array<int> a;for (int i = 0; i < a.size(); i++){a[i] = 1000 + i;}SumArray<int, Array> s(a);cout << s.add() << endl;
}
5、模板的经典错误(补)
5.1 模板二次编译
如果都过不了第一次编译,那么就谈不上第二次编译
- 编译器对模板会进行两次编译
- 第一次编译:发生在实例化模板之前(产生真正函数或真正类之前)只检查模板本身内部代码(只检查基本词法是否正确)
- 模板内部出现的所有标识符是否均有声明
- 对于已知类型的调用要检查调用是否有效
- 对于未知类型调用认为都合理
- 第二次编译:第二次编译发生在实例化模板之后(产生真正函数或真正类之后)结合所使用的类型实参,再次检查模板代码,查看所有调用是否真的都有效
template<typename T>void func(){// 第一次编译时,编译器针对未知类型调用采用隐忍态度,尽量认为都合理//fdf; //错误 模板内部出现的所有标识符是否均有声明 第一次编译A3 a; a.foo(); // 对于已知类型的调用要检查调用是否有效 第一次编译//a.fdfddf();// 错误 在A3类中没有fdfddf 第一次编译T t;t.jsjhdeasde();// 第一次编译不会报错,这是因为对于未知类型调用认为都合理 ,第二次编译会报错,这是因为第二次编译时,编译器结合类型实参,再次检查,所有调用是否真的合理// t.fds<fd>fd();// 这种的第一次编译也会报错
}
int main(){func<int>();return 0;
}
5.2 嵌套依赖
- 问题:由于模板要经过两次编译,在第一次编译模板的代码时,类型形参的具体类型尚不明确,编译器将把类型形参的嵌套类型理解为某个未知类型的静态成员变量,因此编译器看到使用这样的标识符声明变量时会报告错误,这就叫嵌套依赖。
- 解决办法:在类型形参的前面增加一个typename标识符,意在告诉编译器其后是一个类模板的嵌套使用。
class A{
public:class B{public:void foo(){cout << "A::B::foo" << endl;}};
};
template<typename T>void func1(){
// 第一次编译时,会把T::B看做成B是T的静态成员变量,编译器看到使用这样的标识符声明变量时会报告错误
// T::B 类型形参的嵌套类型 typename 告诉编译器B是T(未知类)的嵌套类型typename T::B b;b.foo();
}
int main(){func1<A>();return 0;
}
5.3 利用类型形参调用成员函数模板
- 问题:利用未知类定义的对象来访问成员函数模板时,编译器在第一次编译时无法解析成员函数模板的类型参数列表的<>而报告编译错误。
- 解决方法:在成员函数模板之前增加template关键字,意在告诉编译器其后是一个函数模板实例,编译器就可以正确理解<>了。
class A{
public:template <typename T> void foo(){cout << "A::f00" << endl;}
};
template <typename T> void func2(){T t;// 编译器第一次编译时,未知类型定义的对象,调用方法时,不能带有<> // template告诉编译器后面的是函数模板的实例化t.template foo<int>();
}
int main(){ func2<A>(); return 0;
}
5.4 子类模板访问基类模板
- 问题:在子类模板中访问基类模板的成员,编译器第一次编译时只在子类模板和全局域中搜索使用的标识符号,不会到基类模板中搜索
- 解决方法:在子类模板中可以通过使用作用域限定符或显式使用this指针
template <typename T > class BaseA{
public:int m_i;void foo(){ cout << "BaseA<T>::foo()" << endl; }
};
template<typename T, typename D> class Deri : public BaseA<T>{
public:void bar(/* this*/ ){//m_i = 100; 报错 //foo();BaseA::foo();BaseA::m_i = 100;this->foo();this->m_i = 100;}
};
int main(){Deri<int, int >d;d.bar();return 0;
}
相关文章:
11 类型泛化
11 类型泛化 1、函数模版1.1 前言1.2 函数模版1.3 隐式推断类型实参1.4 函数模板重载1.5 函数模板类型形参的默认类型(C11标准) 2、类模版2.1 类模板的成员函数延迟实例化2.2 类模板的静态成员2.3 类模板的递归实例化2.4 类模板类型形参缺省值 3、类模板…...
UE4_后期_ben_模糊和锐化滤镜
学习笔记,不喜勿喷,侵权立删,祝愿生活越来越好! 本篇教程主要介绍后期处理的简单模糊和锐化滤镜效果,学习之前首先要回顾下上节课介绍的屏幕扭曲效果: 这是全屏效果,然后又介绍了几种蒙版&#…...
Spring Boot中Excel的导入导出的实现之Apache POI框架使用教程
文章目录 前言一、Apache POI 是什么?二、使用 Apache POI 实现 Excel 的导入和导出① 导入 Excel1. 添加依赖2. 编写导入逻辑3. 在 Controller 中处理上传请求 ② 导出 Excel1. 添加依赖2. 编写导出逻辑3. 在 Controller 中处理导出请求 总结 前言 在 Spring Boot …...
CentOS搭建kubernetes集群详细过程(yum安装方式)
kubernetes集群搭建详细过程(yum安装方式) Kubernetes,也被称为K8s,是一个多功能的容器管理工具,它不仅能够协调和调度容器的部署,而且还能监控容器的健康状况并自动修复常见问题。这个平台是在谷歌十多年…...
Java 面试题:Java 的 Exception 和 Error 有什么区别?
在Java编程中,异常处理是确保程序稳健性和可靠性的重要机制。Java提供了一套完善的异常处理框架,通过捕获和处理异常,开发者可以有效地应对程序运行时可能出现的各种问题。在这一框架中,Exception和Error是两个核心概念࿰…...
在Vue 3中,el-select循环el-option的常见踩坑点,value值绑定对象类型?选中效果不准确?
在Vue 3中,el-select 组件是来自 Element Plus UI 库的一部分。 如果你想要设置默认选中的选项,你可以使用 v-model 来绑定选中的值。如果你想要在某个时刻让某个选项显示为已选中,可以设置对应的值到 v-model 绑定的数据。 <template>…...
Qt实现单例模式:Q_GLOBAL_STATIC和Q_GLOBAL_STATIC_WITH_ARGS
目录 1.引言 2.了解Q_GLOBAL_STATIC 3.了解Q_GLOBAL_STATIC_WITH_ARGS 4.实现原理 4.1.对象的创建 4.2.QGlobalStatic 4.3.宏定义实现 4.4.注意事项 5.总结 1.引言 设计模式之单例模式-CSDN博客 所谓的全局静态对象,大多是在单例类中所见,在之前…...
通过nginx转发后应用偶发502bad gateway
序言 学习了一些东西,如何才是真正自己能用的呢?好像就是看自己的潜意识的反应,例如解决了一个问题,那么下次再碰到类似的问题,能直接下意识的去找到对应的信息,从而解决,而不是和第一次碰到一样…...
linux中如何进行yum源的挂载
linux中如何进行yum源的挂载 1.首先创建目录[rootserver /]# mkdir /rhel92.使用mount命令进行、dev/cdrom/的镜像文件进行挂载[rootserver /]# mount /dev/cdrom /rhel9/ 注意:此时设立的是临时命令。重启后则失效,若想在下次开启后仍然挂载&a…...
ffmpeg的部署踩坑及简单使用方式
ffmpeg的使用方式有以下几种: 使用原生安装包 直接在ffmpeg官网上下载安装该软件,加入到环境变量中就可以使用了 优点:简单,灵活,代码中也不用添加其他第三方的包 缺点:需要手动安装ffmpeg,这点比较麻烦 部署-windows 在windows环境下,有时就算加入到了环境变量,…...
misc刷题记录2[陇剑杯 2021]
[陇剑杯 2021]webshell (1)单位网站被黑客挂马,请您从流量中分析出webshell,进行回答: 黑客登录系统使用的密码是_____________。得到的flag请使用NSSCTF{}格式提交。 这里我的思路是,既然要选择的时间段是黑客登录网站以后&…...
AI发展面临的问题? —— AI对创造的重新定义
一、AI的问题描述 AI与数据安全问题:随着AI技术的发展和应用,数据安全问题日益突出。AI模型训练依赖于大量数据,而这些数据中可能包含个人隐私、商业秘密等敏感信息。如果数据在采集、存储、使用过程中处理不当,可能导致数据泄露或…...
k8s学习--OpenKruise详细解释以及原地升级及全链路灰度发布方案
文章目录 OpenKruise简介OpenKruise来源OpenKruise是什么?核心组件有什么?有什么特性和优势?适用于什么场景? 什么是OpenKruise的原地升级原地升级的关键特性使用原地升级的组件原地升级的工作原理 应用环境一、OpenKruise部署1.安…...
上海亚商投顾:沪指缩量调整 PCB概念股持续爆发
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 大小指数昨日走势分化,沪指全天震荡调整,创业板指午后涨超1%。消费电子板块全天强势&a…...
QT属性系统,简单属性功能快速实现 QT属性的简单理解 属性学习如此简单 一文就能读懂QT属性 QT属性最简单的学习
4.4 属性系统 Qt 元对象系统最主要的功能是实现信号和槽机制,当然也有其他功能,就是支持属性系统。有些高级语言通过编译器的 __property 或者 [property] 等关键字实现属性系统,用于提供对成员变量的访问权限,Qt 则通过自己的元对…...
【IEEE出版丨EI检索】2024新型电力系统与电力电子国际会议(NPSPE 2024)
2024新型电力系统与电力电子国际会议(NPSPE 2024)将于8月16日至18日在中国大连举行,本届大会致力于为相关领域的专家和学者提供一个探讨行业热点问题,促进科技进步,增加科研合作的平台。本届大会涵盖新型电力系统和电力…...
【Netty】nio阻塞非阻塞Selector
阻塞VS非阻塞 阻塞 阻塞模式下,相关方法都会导致线程暂停。 ServerSocketChannel.accept() 会在没有建立连接的时候让线程暂停 SocketChannel.read()会在没有数据的时候让线程暂停。 阻塞的表现就是线程暂停了,暂停期间不会占用CPU,但线程…...
ES 操作
1、删除索引的所有记录 curl -X POST "localhost:9200/<index-name>/_delete_by_query" -H Content-Type: application/json -d {"query": {"match_all": {}} }POST /content_erp_nlp_help/_delete_by_query { "query": { &quo…...
uniapp如何实现跳转
在 UniApp 中,页面跳转主要可以通过两种方式实现:使用 <navigator> 组件和调用 UniApp 提供的导航 API。以下是这两种方式的详细说明: 1. 使用 <navigator> 组件 <navigator> 组件允许你在页面上创建一个可点击的元素&am…...
Stable-Diffusion-WebUI 常用提示词插件
SixGod提示词插件 SixGod提示词插件可以帮助用户快速生成逼真、有创意的图像。其中包含,清空正向提示词”和“清空负向提示词、提示词起手式包含人物、服饰、人物发型等各个维度的提示词、一键清除正面提示词与负面提示词、随机灵感关键词、提示词分类组合随机、动…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
