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

(学习总结20)C++11 可变参数模版、lambda表达式、包装器与部分新内容添加

C++11 可变参数模版、lambda表达式、包装器与部分新内容添加

  • 一、可变参数模版
    • 基本语法及原理
    • 包扩展
    • emplace系列接口
  • 二、lambda表达式
    • lambda表达式语法
    • 捕捉列表
    • lambda的原理
    • lambda的应用
  • 三、包装器
    • bind
    • function
  • 四、部分新内容添加
    • 新的类功能
      • 1.默认的移动构造和移动赋值
      • 2.声明时给缺省值
      • 3.defult 和 delete
      • 4.final 与 override
    • STL中一些变化

以下代码环境为 VS2022 C++

一、可变参数模版

基本语法及原理

C++11 支持可变参数模板,也就是说支持可变数量参数的函数模板和类模板,可变数目的参数被称为参数包。

存在两种参数包:模板参数包,表示零或多个模板参数;函数参数包,表示零或多个函数参数。

我们用省略号来指出一个模板参数或函数参数表示一个包。在模板参数列表中,class… 或 typename… 指出接下来的参数表示零或多个类型列表;在函数参数列表中,类型名后面跟 … 指出接下来表示零或多个形参对象列表。

函数参数包可以用左值引用或右值引用表示,跟上一篇文章讲的普通模板一样,每个参数实例化时遵循引用折叠规则

#include <iostream>
#include <vector>
using namespace std;template<class ...Args>
class one
{;
};template<class ...Args>
void get(Args... args)
{;
}template<class ...Args>
void set(const Args&... args)
{;
}template<class ...Args>
void print(Args&&... args)
{;
}int main()
{get(2, "111111", 5 + 6);set(5.1, 'h', 'e');print(1.5, 5.1f, "haha");print("hehe");one<int, double, long long, char, float> get1;one<string, vector<long long>> get2;one<long long> get3;return 0;
}

可变参数模板的原理跟模板类似,本质还是在编译时实例化对应类型和个数的多个函数

这里可以使用 sizeof… 运算符去计算参数包中参数的个数。

#include <iostream>
using namespace std;template<class ...Args>
void print(Args&&... args)
{cout << sizeof...(args) << endl;
}int main()
{print(1, 2, 3);				// 3个print(1.5, 5.1f, "haha");	// 3个print();					// 0个print("hehe");				// 1个return 0;
}

包扩展

对于一个参数包,除了能计算它的参数个数,我们能做的唯一的事情就是扩展它,当扩展一个包时,我们还要提供用于每个扩展元素的模式,扩展一个包就是将它分解为构成的元素,对每个元素应用模式,获得扩展后的列表。我们通过在模式的右边放一个省略号 … 来触发扩展操作。

#include <iostream>
using namespace std;void print()				// 当参数为 0 时自动匹配无参 print 递归终止
{cout << endl;
}template<class T, class ...Args>
void print(T&& x, Args&&... args)
{cout << x << " ";		// 递归调用 print ,将接收到的第一个参数进行打印print(args...);			// 用包扩展将剩下的参数传给下一个 print
}// 这里用 print(1.5, 5.1f, "haha"); 为例
// 首先会实例化 void print(double x, float y, string z) 函数
// 先打印 x,再通过包扩展将 y, z 传给下一个 print
//void print(double x, float y, string z)
//{
//	cout << x << " ";
//	print(y, z);
//}
// 下一个实例化为 void print(float y, string z) 函数
// 先打印 y,再通过包扩展将 z 传给下一个 print
//void print(float y, string z)
//{
//	cout << y << " ";
//	print(z);
//}
// 下一个实例化为 void print(string z) 函数
// 打印 z,此时包扩展里的参数为 0,会匹配 print() 函数结束包扩展
//void print(string z)
//{
//	cout << z << " ";
//	print();
//}int main()
{print(1, 2, 3);print(1.5, 5.1f, "haha");print();print("hehe");return 0;
}

C++11 还支持更复杂的包扩展,直接将参数包依次展开作为实参给一个函数去处理。

#include <iostream>
using namespace std;template<class T>
int show(T&& x)
{cout << x << " ";return 0;
}template<class ...a>
void get(a&& ...x)
{;
}template<class ...Args>
class one
{
public:one() = default;
};template<class ...Args>
void print(Args&&... args)
{// 展开发生的位置一般在函数参数列表、成员初始化列表、属性列表、类模版参数列表等// show(args)... 表示每个参数都会调用一次 show()// 若有三个参数可表示为// show(one), show(two), show(three)// int arr[] = { 0, show(one), show(two), show(three) };// get(show(one), show(two), show(three));int arr[] = { 0, show(args)... };	// 数组执行顺序是从左到右//get(show(args)...);				// 函数参数执行是从右到左one<Args...> get;				// 类型可在类模板参数列表展开cout << endl;
}int main()
{print(1, 2, 3);print(1.5, 5.1f, "haha");print();print("hehe");return 0;
}

emplace系列接口

C++11 以后 STL 容器新增了 emplace 系列的接口,emplace 系列的接口均为模板可变参数,功能上兼容 push 和 insert 系列,但是 emplace 还支持新操作,假设容器为container<Type>,emplace 支持直接传入构造 Type 对象的参数,这样有些场景会更高效一些,可以直接在容器空间上构造 Type 对象。

emplace 系列相对于 insert 和 push 系列总体而言是更高效,可以平替后两者。

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<pair<string, int>> arr;pair<string, int> get1 = { "1111111111", 1 };// 传左值一样走拷贝构造arr.push_back(get1);arr.emplace_back(get1);// 传右值一样走移动构造arr.push_back(pair<string, int>("22222222", 5));arr.emplace_back(pair<string, int>("22222222", 5));// push_back 会先 有参构造 再 移动构造arr.push_back({ "333333333", 10 });// emplace_back 会将参数直接传进去进行有参构造,没有移动构造,此时效率高一点arr.emplace_back("333333333", 10);return 0;
}

二、lambda表达式

lambda表达式语法

lambda 表达式本质是一个匿名函数对象,跟普通函数不同的是它可以定义在函数内部。

lambda 表达式语法使用层而言没有类型,所以一般是用 auto 或者 模板参数定义的对象 去接收 lambda 对象。

lambda表达式的格式: [capture-list](parameters)->return type { function body }

[capture-list] : 捕捉列表,该列表总是出现在 lambda 函数的开始位置,编译器根据 [] 来判断接下来的代码是否为 lambda 函数,捕捉列表能够捕捉上下文中的变量供 lambda 函数使用,捕捉列表可以传值和传引用捕捉。捕捉列表为空也不能省略。

(parameters) :参数列表,与普通函数的参数列表功能类似,但如果不需要参数传递,则可以将 () 省略。

->return type :返回值类型,用追踪返回类型形式去声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。

{ function body } :函数体,函数体内的实现跟普通函数完全类似,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量,函数体为空也不能省略。

#include <iostream>
using namespace std;int main()
{auto add = [](int x, int y)->int { return x + y; };cout << add(10, 20) << endl;// 1. [] 不能省略// 2. () 可以省略// 3. ->return type 可以省略// 4. {} 不能省略auto func1 = [] {};func1();auto swap = [](int& one, int& two)->void{int temp = one;one = two;two = temp;};int a = 100;int b = 1;cout << "a == " << a << endl << "b == " << b << endl << endl;swap(a, b);cout << "a == " << a << endl << "b == " << b << endl;return 0;
}

捕捉列表

lambda 表达式中默认只能用 lambda 函数体和参数中的变量,如果想用外层作用域中的变量就需要进行捕捉。

  1. 第一种捕捉方式是在捕捉列表中显示的传值捕捉和传引用捕捉,捕捉的多个变量用逗号分割。[ x, y, &z ] 表示 x 和 y 值捕捉,z 引用捕捉。
#include <iostream>
using namespace std;int main()
{int x = 0;int y = 10;int z = 100;int t = 1000;auto func1 = [x, y, &z]{cout << x << " " << y << " " << z << endl;};func1();return 0;
}
  1. 第二种捕捉方式是在捕捉列表中隐式捕捉,在捕捉列表写一个 “ = ” 表示隐式值捕捉,在捕捉列表写一个 “ & ” 表示隐式引用捕捉,这样 lambda 表达式中用了哪些变量,编译器就会自动捕捉哪些变量。
#include <iostream>
using namespace std;int main()
{int x = 0;int y = 10;int z = 100;int t = 1000;auto func1 = [=]{cout << "func1 " << x << " " << y << " " << z << endl;};auto func2 = [&]{cout << "func2 " << x << " " << y << " " << z << endl;};func1();func2();return 0;
}
  1. 第三种捕捉方式是在捕捉列表中混合使用隐式捕捉和显示捕捉。当使用混合捕捉时,第一个元素必须是 “ & ” 或 “ = ”,并且 “ & ” 混合捕捉时,后面的捕捉变量必须是值捕捉,同理 “ = ” 混合捕捉时,后面的捕捉变量必须是引用捕捉。[ =, &x ] 表示其他变量隐式值捕捉,x 引用捕捉;[ &, z, y ] 表示其他变量引用捕捉,z 和 y 值捕捉。
#include <iostream>
using namespace std;int main()
{int x = 0;int y = 10;int z = 100;auto func1 = [=, &x]{cout << "func1 " << x << " " << y << " " << z << endl;};auto func2 = [&, z, y]{cout << "func2 " << x << " " << y << " " << z << endl;};func1();func2();return 0;
}

lambda 表达式如果在函数局部域中,它可以捕捉 lambda 位置之前定义的变量,不能捕捉静态局部变量和全局变量,静态局部变量和全局变量也不需要捕捉,在 lambda 表达式中可以直接使用。这也意味着 lambda 表达式如果定义在全局位置,捕捉列表必须为空。

默认情况下, lambda 捕捉列表是被 const 修饰的,则传值捕捉的过来的对象不能修改,mutable 加在参数列表的后面可以取消其常量性,使用该修饰符后,传值捕捉的对象就可以修改了,但是修改的是形参对象,不会影响实参。使用该修饰符后,参数列表即使为空也不可省略

#include <iostream>
using namespace std;string str1 = "全局变量";auto func1 = []			// 定义在全局位置,捕捉列表必须为空{cout << str1 << endl;cout << "hello world!" << endl;};void test()
{string str4 = "另一个函数中的局部变量";static string str5 = "另一个函数中的静态局部变量";
}int main()
{string str2 = "局部变量";static string str3 = "静态局部变量";auto func2 = [&str2]{cout << str1 << endl;cout << str2 << endl;cout << str3 << endl;//cout << str4 << endl;		// 无法使用其他局部域变量//cout << str5 << endl;		// 无法使用其他局部域静态变量};func1();func2();int a = 10;int b = 20;int c = 30;int d = 40;cout << endl << a << " " << b << " " << c << " " << d << endl;auto func3 = [a, b, &c, &d]{//a = 0;	// 不可修改//b = 0;d = c = 1000;};func3();cout << a << " " << b << " " << c << " " << d << endl;// 传值捕捉是拷贝,并被 const 修饰,// mutable 可以去掉 const 属性,使得值捕捉变量可修改auto func4 = [a, b, &c, &d]()mutable ->void{a = 0;		// mutable 修饰后可修改,但不会影响外面被值捕捉的值b = 0;d = c = -99;};func4();cout << a << " " << b << " " << c << " " << d << endl;return 0;
}

lambda的原理

lambda 的原理和 范围for 很像,编译后从汇编指令层的角度看,压根就没有 lambda 和 范围for 这样的东西。范围for 底层是迭代器,而 lambda 底层是仿函数对象,也就说如果我们写了一个 lambda 以后,编译器会生成一个对应的仿函数的类。

仿函数的类名是编译器按一定规则生成的,保证不同的 lambda 生成的类名不同。

lambda 参数 / 返回类型 / 函数体 就是仿函数 operator() 的 参数 / 返回类型 / 函数体, lambda 的捕捉列表本质是生成的仿函数类的成员变量,也就是说捕捉列表的变量都是 lambda 类构造函数的实参,如果隐式捕捉,使用哪些就传哪些对象。

lambda的应用

一般使用的可调用对象只有函数指针和仿函数对象,函数指针的类型定义起来比较麻烦,仿函数要定义一个类,相对也会比较麻烦。使用 lambda 去定义可调用对象,既简单又方便。

lambda 在很多地方用起来也很好用。比如线程中定义线程的执行函数逻辑,智能指针中定制删除器等。

三、包装器

bind

std::bind 是一个函数模板,它是一个可调用对象的包装器,可以把它看做一个函数适配器,对接收的可调用对象进行处理后返回另一个可调用对象。 std::bind 可以用来调整参数个数和参数顺序

std::bind 在 <functional> 这个头文件中。

调用 std::bind 的一般形式: auto newCallable = std::bind(callable, arg_list);其中 newCallable 本身是一个可调用对象,arg_list 是一个逗号分隔的参数列表,对应给定的 callable 的参数。当调用 newCallable 时,newCallable 会调用 callable,并传给它 arg_list 中的参数。

arg_list 中的参数可能包含形如 _n 的名字,其中 n 是一个整数,这些参数是占位符,表示 newCallable 的参数,它们占据了传递给 newCallable 的参数的位置。数值 n 表示生成的可调用对象中参数的位置:_1 为 newCallable 的第一个参数,_2 为第二个参数,以此类推。_1 / _2 / _3… 这些占位符放在 placeholders 的一个命名空间中。

#include <iostream>
#include <iostream>
#include <functional>
using namespace std;using placeholders::_1;
using placeholders::_2;int add(int a, int b)
{return a + b;
}struct sub
{int operator()(int a, int b){return a - b;}
};int main()
{// bind 本身返回一个仿函数对象auto tadd = bind(add, _1, _2);auto tsub = bind(sub(), _1, _2);auto tmul = bind([](int a, int b) {return a * b; }, _1, _2);int a = 10;int b = 5;cout << tadd(a, b) << endl;cout << tsub(a, b) << endl;cout << tmul(a, b) << endl << endl;// bind 可以调整对象的参数顺序(但不常用)。// _1 代表第一个实参传入对象参数的位置// _2 代表第二个实参传入对象参数的位置// ... 其它同理auto radd = bind(add, _2, _1);auto rsub = bind(sub(), _2, _1);auto rmul = bind([](int a, int b) {return a * b; }, _2, _1);cout << radd(a, b) << endl;cout << rsub(a, b) << endl;cout << rmul(a, b) << endl << endl;// bind 调整对象参数个数(常用)。auto sub_10 = bind(sub(), _1, 10);auto _100_sub = bind(sub(), 100, _1);cout << sub_10(50) << endl;cout << _100_sub(-10) << endl;return 0;
}

function

std::function 是一个类模板,也是一个包装器。 std::function 的实例对象可以包装存储其他的可调用对象,包括函数指针、仿函数、 lambda 、 bind 表达式等,存储的可调用对象被称为 std::function 的目标。若 std::function 不含目标,则称它为空。调用空 std::function 的目标会导致抛出 std::bad_function_call 异常。

function 被定义 <functional> 头文件中。std::function - cppreference.com 是 std::function 的官方文件链接。

函数指针、仿函数、 lambda 等可调用对象的类型各不相同, std::function 的优势就是统一类型,对它们都可以进行包装,这样在很多地方就方便声明可调用对象的类型。

#include <iostream>
#include <functional>
using namespace std;int add(int a, int b)
{return a + b;
}struct sub
{int operator()(int a, int b){return a - b;}
};struct func
{static string getString(){return "得到字符串";}int getNumber(){return 10000;}
};int main()
{//function 的 <> 中参数放在 () 里,返回值在 () 的左边:function<string()> print = [] { return "hello world!"; };function<int(int, int)> tsub = sub();function<int(int, int)> tadd = add;cout << print() << endl;cout << tsub(10, 2) << endl;cout << tadd(10, 2) << endl;// 对于静态类成员函数function<string()> getstr1 = func::getString;function<string()> getstr2 = &func::getString;cout << getstr1() << endl;cout << getstr2() << endl;// 对于普通成员函数有麻烦的地方,因为有隐式的 this 指针,调用 function 时需要传入对象function<int(func&)> getnum1 = &func::getNumber;//function<int(func&)> getnum1 = func::getNumber;	普通成员函数需要取地址符号 '&'func one;cout << getnum1(one) << endl;// 解决方法:使用 bind 将对象的 this 指针进行绑定,方便调用function<int()> getnum2 = bind(&func::getNumber, func());cout << getnum2() << endl;return 0;
}

四、部分新内容添加

新的类功能

1.默认的移动构造和移动赋值

原来 C++ 类中,有 6 个默认成员函数:构造函数 / 析构函数 / 拷贝构造函数 / 拷贝赋值重载 / 取地址重载 / const 取地址重载,最后重要的是前 4 个,后两个用处不大,默认成员函数就是我们不写编译器会生成一个默认的。C++11 新增了两个默认成员函数,移动构造函数 和 移动赋值运算符重载。

如果没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个。则编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造。

如果没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造完全类似)

如果自己提供了移动构造或者移动赋值,编译器就不会自动提供拷贝构造和拷贝赋值。

2.声明时给缺省值

这部分内容可参考:(学习总结9)C++学习的初步总结 —— 三、缺省参数

3.defult 和 delete

C++11 可以更好的控制要使用的默认函数。假设要使用某个默认的函数,但是因为一些原因这个函数没有默认生成。如果提供了拷贝构造,就不会生成移动构造,则可以使用 default 关键字显示指定移动构造生成。

如果能想要限制某些默认函数的生成,在 C++98 中,是该函数设置成 private,并且只声明,这样只要其他人想要调用就会报错。在 C++11 中更简单,只需在该函数声明加上 = delete 即可,该语法指示编译器不生成对应函数的默认版本,称 = delete 修饰的函数为删除函数。

#include <iostream>
using namespace std;class One
{
public:One() = default;~One() = default;One(const One&) = default;One& operator=(const One&) = default;One(One&&) = default;One& operator=(One&&) = default;
};class Two
{
public:Two() = delete;
};int main()
{One get1;//Two get2;		// 默认构造已经删除,会报错return 0;
}

4.final 与 override

这部分内容可参考:
(学习总结17)C++继承 —— 四、派生类的默认成员函数 —— 实现一个不能被继承的类
(学习总结18)C++多态 —— 二、多态的定义及实现 —— 6. override 和 final 关键字

STL中一些变化

下图圈起来的就是 STL 中的新容器,但是实际上常用的是 unordered_map 和unordered_set。

在这里插入图片描述

STL 中容器的新接口也不少,最重要的就是右值引用和移动语义相关的 push / insert / emplace 系列接口 和 移动构造与移动赋值,还有 initializer_list 版本的构造等,容器的 范围for 遍历支持。

相关文章:

(学习总结20)C++11 可变参数模版、lambda表达式、包装器与部分新内容添加

C11 可变参数模版、lambda表达式、包装器与部分新内容添加 一、可变参数模版基本语法及原理包扩展emplace系列接口 二、lambda表达式lambda表达式语法捕捉列表lambda的原理lambda的应用 三、包装器bindfunction 四、部分新内容添加新的类功能1.默认的移动构造和移动赋值2.声明时…...

备份和容灾之区别(The Difference between Backup and Disaster Recovery)

备份和容灾之区别 备份和容灾都是数据安全常见的保障手段&#xff0c;但是一般在正常业务运行时是无需用到这两个技术手段的。只有在业务已经崩溃&#xff0c;需要进行业务恢复时&#xff0c;这两种技术的价值才能真正体现。所以&#xff0c;备份和容灾可以说是数据安全最后两…...

Go语言之路————数组、切片、map

Go语言之路————数组、切片、map 前言一、数组二、切片三、map 前言 我是一名多年Java开发人员&#xff0c;因为工作需要现在要学习go语言&#xff0c;Go语言之路是一个系列&#xff0c;记录着我从0开始接触Go&#xff0c;到后面能正常完成工作上的业务开发的过程&#xff…...

Kotlin Bytedeco OpenCV 图像图像57 图像ROI

Kotlin Bytedeco OpenCV 图像图像57 图像ROI 1 添加依赖2 测试代码3 测试结果 1 添加依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns"http://maven.apache.o…...

字符编码通过字节数组向16进制的互转【终端设备通讯案例篇】:微信小程序 JavaScript字符串转gb2312 字符编码,以16进制字符串传输。(接收蓝牙设备的信息,发送北斗终端消息)

文章目录 引言I 原理II 案例一:微信小程序字符串转gb2312 字符编码,以16进制字符串传输。字节数组 转16进制字符串微信小程序字符串转gb2312 字节数组(utf8ToGb2312Bytes)demo:gb2312 字符编码->字节数组->16进制字符串III 案例二: 小程序接收gb2312 的16进制字符串…...

LabVIEW与WPS文件格式的兼容性

LabVIEW 本身并不原生支持将文件直接保存为 WPS 格式&#xff08;如 WPS 文档或表格&#xff09;。然而&#xff0c;可以通过几种间接的方式实现这一目标&#xff0c;确保您能将 LabVIEW 中的数据或报告转换为 WPS 可兼容的格式。以下是几种常见的解决方案&#xff1a; ​ 导出…...

协程(还需要输入3个字)

昨天我偶然听到协程这个概念&#xff0c;不禁好奇地了解了一下&#xff0c;做些笔记如下&#xff1a; 一、什么是协程 协程是在线程内部&#xff0c;由程序自己控制逻辑&#xff0c; 显式地让出控制权&#xff08;yield&#xff09;来实现任务切换&#xff0c;而不是由操作系…...

系统架构设计师-第1章-计算机系统知识要点

【本章学习建议】 根据考试大纲&#xff0c;本章主要考查系统架构设计师单选题&#xff0c;预计考1分左右。第二版教材2.2节增加了本块内容&#xff0c;但较为简略&#xff0c;需要课程补充&#xff0c;属于非重点内容。 1.1 计算机硬件组成 计算机的基本硬件系统由运算器、控…...

Linux -- 初识HTTP协议

目录 什么是HTTP协议 什么是 URL &#xff1f; 理解 URL 初识HTTP 请求与响应格式 代码验证 gitee HTTP.hpp 结果 什么是HTTP协议 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;主要用于客户端&#xff08;通常是浏览器&#…...

【已解决】我和ollama运行的qwen2.5大模型通信,总是返回GGGG?

起因&#xff1a; 和大模型通信的时候&#xff0c;总是返回 GGG 之类的乱码。 curl查询返回到结果&#xff1a; 既然curl通信不行&#xff0c;直接在控制台聊天呢&#xff1f; 话都说不明白&#xff0c;我火了&#xff0c;结果一查&#xff0c;我熄火了&#xff0c;是ollama…...

在Mac mini上实现本地话部署AI和知识库

在Mac mini上实现本地话部署AI和知识库 硬件要求&#xff1a;大模型AI&#xff0c;也叫LLM&#xff0c;需要硬件支持&#xff0c;常见的方式有2种&#xff1a;一种是采用英伟达之类支持CUDA库的GPU芯片或者专用AI芯片&#xff1b;第二种是采用苹果M系列芯片架构的支持统一内存架…...

SQL和MySQL以及DAX的日期表生成?数字型日期?将生成的日期表插入到临时表或者实体表中

几种生成日期表的方法 如何用SQL语句生成日期表呢&#xff1f; 如何用MySQL语句生成日期表呢&#xff1f; 如何用DAX语句生成日期表呢&#xff1f; 1. MySQL生成日期表 1.1 日期格式&#xff1a;yyyy-MM-dd 字符型 2024-01-02 -- 生成日期表 WITH RECURSIVE temp_dateTable …...

win32汇编环境,窗口程序中基础列表框的应用举例

;运行效果 ;win32汇编环境,窗口程序中基础列表框的应用举例 ;比如在窗口程序中生成列表框&#xff0c;增加子项&#xff0c;删除某项&#xff0c;取得指定项内容等 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;以下是ASM文件 ;>>>>>>>>>>>…...

Sentinel配置流控规则详解

前言 在微服务架构中&#xff0c;流量控制&#xff08;Flow Control&#xff09;是保障服务稳定性的重要手段之一。Sentinel作为一款开源的流量控制、熔断降级Java库&#xff0c;以其丰富的应用场景和完善的监控能力&#xff0c;在微服务保护中扮演了重要角色。本文将详细介绍…...

opencv图像基础学习

2.3图像的加密解密 源码如下&#xff1a; import cv2 import numpy as np import matplotlib.pyplot as plt def passImg():imgcv2.imread(./image/cat.jpg,0)h,wimg.shape#生成一个密码&#xff0c;加密key_imgnp.random.randint(0,256,size(h,w),dtypenp.uint8)img_addmcv2…...

递归40题!再见递归

简介&#xff1a;40个问题&#xff0c;有难有易&#xff0c;均使用递归完成&#xff0c;需要C/C的指针、字符串、数组、链表等基础知识作为基础。 1、数字出现的次数 由键盘录入一个正整数&#xff0c;求该整数中每个数字出现的次数。 输入&#xff1a;19931003 输出&#xf…...

javadoc使用dos命令生成api文档演示

新建一个文本后缀改java&#xff0c;名字改为类名 文本内容&#xff1a; /** * author ZZJ * version jdk23.0.1 */ public class Test{/*** 求输入两个参数范围以内整数的和* param n 接收的第一个参数&#xff0c;范围起点* param m 接收的第二个参数&#xff0c;范围终点*…...

OpenAI推出首个AI Agent!日常事项自动化处理!

2025 年1月15日&#xff0c;OpenAI 正式宣布推出一项名为Tasks的测试版功能 。 该功能可以根据你的需求内容和时间实现自动化处理。比方说&#xff0c;你可以设置每天早晨 7 点获取天气预报&#xff0c;或定时提醒遛狗等日常事项。 看到这里&#xff0c;有没有一种熟悉的感觉&a…...

uniapp实现“到这儿去”、拨打电话功能

"到这儿去" 在 UniApp 中实现“到这儿去”的功能,即调起地图导航至指定位置,对于不同的平台(小程序、H5、App)有不同的处理方式。下面将简单介绍如何在这些平台上实现该功能,并讨论位置信息的获取。后面需求会用到,先来找一些相关资料,并不一定很准确,但也来…...

T-SQL语言的计算机基础

T-SQL语言的计算机基础 引言 在当今信息技术迅猛发展的时代&#xff0c;数据已成为企业和组织决策的重要基础。而处理和管理数据的工具和语言也日益成为IT专业人员必备的技能之一。T-SQL&#xff08;Transact-SQL&#xff09;作为微软SQL Server数据库的扩展&#xff0c;是一…...

SpringBoot + Websocket实现系统用户消息通知

1、引入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.7</version><relativePath/> </parent> <dependencies><dependency>…...

基于 HTML5 Canvas 制作一个精美的 2048 小游戏--day 1

基于 HTML5 Canvas 制作一个精美的 2048 小游戏 在这个快节奏的生活中&#xff0c;简单而富有挑战性的游戏总能给我们带来乐趣。2048 是一款受欢迎的益智游戏&#xff0c;不仅考验智力&#xff0c;还能让人回味无穷。今天&#xff0c;我带领大家将一起学习如何使用 HTML5 Canv…...

macos arm 本地/docker/本地k8s 安装jupyterhub 并登陆

概述 很多文章写的启动官方docker镜像后,新建linux用户即可直接登录,不知道是否版本原因,总之目前最新版我亲测不可以,踩坑两天,这里记录下解决过程,以及各种细节在文档中的位置.以及为什么官方镜像不能直接使用的原因. part1 本地安装jupyterhub https://jupyterhub.readth…...

go采集注册表

package mainimport ("fmt""golang.org/x/sys/windows/registry""log""os""strconv""strings" )func USBSTOR_Enum() {// 打开注册表键keyPath : SYSTEM\CurrentControlSet\Services\USBSTOR\Enumk, err : regist…...

Java连接TDengine和MySQL双数据源

git文件地址&#xff1a;项目首页 - SpringBoot连接TDengine和MySQL双数据源:SpringBoot连接TDengine和MySQL双数据源 - GitCode 1、yml配置 spring:datasource:druid:mysql:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/testusername: roo…...

配置AOSP下载环境

1#curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo 2#repo init -u https://android.googlesource.com/platform/manifest 3#清华镜像站帮助页 https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/ 4#同步安卓AOSP 这里是安卓13 repo init -u htt…...

SpringBoot源码解析(七):应用上下文结构体系

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args Sp…...

5 分钟复刻你的声音,一键实现 GPT-Sovits 模型部署

想象一下&#xff0c;只需简单几步操作&#xff0c;就能生成逼真的语音效果&#xff0c;无论是为客户服务还是为游戏角色配音&#xff0c;都能轻松实现。GPT-Sovits 模型&#xff0c;其高效的语音生成能力为实现自然、流畅的语音交互提供了强有力的技术支持。本文将详细介绍如何…...

数字化时代,传统代理模式的变革之路

在数字化飞速发展的今天&#xff0c;线上线下融合&#xff08;O2O&#xff09;成了商业领域的大趋势。这股潮流&#xff0c;正猛烈冲击着传统代理模式&#xff0c;给它带来了新的改变。 咱们先看看线上线下融合现在啥情况。线上渠道那是越来越多&#xff0c;企业纷纷在电商平台…...

python爬虫爬取淘宝商品比价||淘宝商品详情API接口

最近在学习北京理工大学的爬虫课程&#xff0c;其中一个实例是讲如何爬取淘宝商品信息&#xff0c;现整理如下&#xff1a; 功能描述&#xff1a;获取淘宝搜索页面的信息&#xff0c;提取其中的商品名称和价格 探讨&#xff1a;淘宝的搜索接口 翻页的处理 技术路线:requests…...

HunyuanVideo 文生视频模型实践

HunyuanVideo 文生视频模型实践 flyfish 运行 HunyuanVideo 模型使用文本生成视频的推荐配置&#xff08;batch size 1&#xff09;&#xff1a; 模型分辨率(height/width/frame)峰值显存HunyuanVideo720px1280px129f60GHunyuanVideo544px960px129f45G 本项目适用于使用 N…...

CSRF攻击XSS攻击

概述 ​在 HTML 中&#xff0c;<a>, <form>, <img>, <script>, <iframe>, <link> 等标签以及 Ajax 都可以指向一个资源地址&#xff0c;而所谓的跨域请求就是指&#xff1a;当前发起请求的域与该请求指向的资源所在的域不一样。这里的域指…...

vue3学习日记8 - 一级分类

最近发现职场前端用的框架大多为vue&#xff0c;所以最近也跟着黑马程序员vue3的课程进行学习&#xff0c;以下是我的学习记录 视频网址&#xff1a; Day2-17.Layout-Pinia优化重复请求_哔哩哔哩_bilibili 学习日记&#xff1a; vue3学习日记1 - 环境搭建-CSDN博客 vue3学…...

Notepad++移除所有空格

1.打开Notepad。 2.打开你想要编辑的文件。 3.按下 Ctrl H 打开查找和替换对话框&#xff0c;并选择 “正则表达式”。 4.在 “查找目标” 框中输入 \s。 5.在 “替换为” 框中留空&#xff0c;不填写任何内容。 6.点击 “全部替换” 按钮。...

JavaSE第八天

一、继承之super关键字 super关键字&#xff1a; 一个引用变量&#xff0c;用于引用父类对象 父类和子类都具有相同的命名方法&#xff0c;要调用父类方法时使用 父类和子类都具有相同的命名属性&#xff0c;要调用父类中的属性时使用 super也是父类的构造函数&#xff0c;…...

ideal jdk报错如何解决

例如: 可能一:环境变量中未配置 请在Path中加入并将要使用的最好置顶,如 可能二:项目结构中语言级别错误: 可能三:Maven工程中,对于模块要单独设置jdk: 如: 未设置则为默认,在博主本次展示中为:...

嵌入式Linux ntpclient的使用

ntpclient是一个用于与NTP&#xff08;Network Time Protocol&#xff0c;网络时间协议&#xff09;服务器通信并测量系统时间的工具。我这里用的是"ntpclient_2024_132"。下载源码编译后会得到一个ntpclient程序。 下面是对ntpclient每个选项的解释&#xff1a; -…...

25/1/15 嵌入式笔记 初学STM32F108

GPIO初始化函数 GPIO_Ini&#xff1a;初始化GPIO引脚的模式&#xff0c;速度和引脚号 GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化GPIOA的引脚0 GPIO输出控制函数 GPIO_SetBits&#xff1a;将指定的GPIO引脚设置为高电平 GPIO_SetBits(GPIOA, GPIO_Pin_0); // 将GPIO…...

【练习】力扣热题100 字符串解码

题目 给定一个经过编码的字符串&#xff0c;返回它解码后的字符串。 编码规则为: k[encoded_string]&#xff0c;表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k保证为正整数。 你可以认为输入字符串总是有效的&#xff1b;输入字符串中没有额外的空格&#xff0c…...

1.快慢指针-力扣-283-移动零

题目描述 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 用例 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nu…...

5. 使用springboot做一个音乐播放器软件项目【业务逻辑开发】

#万物oop 上一章文章 我们做了音乐播放器 数据表的创建。参加地址&#xff1a; https://blog.csdn.net/Drug_/article/details/145093705 今天分享的这篇文章就是根据数据表 来写 业务逻辑 。 今天我们主要是实现管理后台的功能。 对于这篇文章 的理解 需要小伙伴有 springbo…...

配置正确spring-boot工程启动的时候报错dynamic-datasource Please check the setting of primary

一个两年没有碰的spring-boot工程&#xff0c;启动时报错。因为用了baomidou的多源数据库配置&#xff0c;因此启动时报错primary没有正确配置。经过检查&#xff0c;确定配置文件配置正确。 报错原因是没有读到正确的配置文件。pom文件里的resources标签重定义&#xff0c;把…...

Freeswitch使用media_bug能力实现回铃音检测

利用freeswitch的media bug能力来在智能外呼时通过websocket对接智能中心的声音检测接口&#xff0c;来实现回铃音检测&#xff0c;来判断用户当前是否已响应&#xff0c;拒接&#xff0c;关机等。 1.回铃音处理流程 2.模块源码目录结构 首先新建一个freeswitch的源码的src/a…...

Kubernetes(k8s)和Docker Compose本质区别

Kubernetes&#xff08;简称 k8s&#xff09;和 Docker Compose 是容器编排领域的两大重要工具&#xff0c;虽然它们都用于管理和编排容器化应用&#xff0c;但在设计目标、功能特性、使用场景和复杂度上存在显著差异。以下将从多个方面详细探讨 Kubernetes 和 Docker Compose …...

OSI七层协议——分层网络协议

OSI七层协议&#xff0c;顾名思义&#xff0c;分为七层&#xff0c;实际上七层是不存在的&#xff0c;是人为的进行划分,让人更好的理解 七层协议包括&#xff0c;物理层(我),数据链路层(据),网络层(网),传输层(传输),会话层(会),表示层(表),应用层(用)(记忆口诀->我会用表…...

RabbitMQ 客户端 连接、发送、接收处理消息

RabbitMQ 客户端 连接、发送、接收处理消息 一. RabbitMQ 的机制跟 Tcp、Udp、Http 这种还不太一样 RabbitMQ 服务&#xff0c;不是像其他服务器一样&#xff0c;负责逻辑处理&#xff0c;然后转发给客户端 而是所有客户端想要向 RabbitMQ服务发送消息&#xff0c; 第一步&a…...

SQL ON与WHERE区别

在 MySQL 中&#xff0c;ON 和 WHERE 都用于过滤数据&#xff0c;但它们的使用场景和作用有所不同&#xff0c;尤其是在涉及 JOIN 操作时。下面通过具体的例子来说明它们的区别。 1. ON 的作用 ON 用于指定表之间的连接条件&#xff0c;决定哪些行应该被连接在一起。它在 JOI…...

[创业之路-254]:《华为数字化转型之道》-1-华为是一个由客户需求牵引、高度数字化、高度智能化、由无数个闭环流程组成的价值创造、评估、分配系统。

前言&#xff1a; 华为是一个由客户需求牵引、高度数字化、高度智能化、由无数个闭环流程组成的价值创造、评估、分配系统。华为的流程大到战略&#xff0c;小到日常工作&#xff0c;是由无数个自我调节自我优化的数字化闭环控制流程组成&#xff0c;大闭环套小闭环&#xff0…...

免费为企业IT规划WSUS:Windows Server 更新服务 (WSUS) 之快速入门教程(一)

哈喽大家好&#xff0c;欢迎来到虚拟化时代君&#xff08;XNHCYL&#xff09;&#xff0c;收不到通知请将我点击星标&#xff01;“ 大家好&#xff0c;我是虚拟化时代君&#xff0c;一位潜心于互联网的技术宅男。这里每天为你分享各种你感兴趣的技术、教程、软件、资源、福利…...

异步任务与定时任务

一、异步任务 基于TaskExecutionAutoConfiguration配置类中&#xff0c;注册的ThreadPoolTaskExecutor线程池对象进行异步任务执行。 (一)手动执行异步任务 在yml中配置线程池参数 spring: task:execution:pool:core-size: 5 # 核心线程数max-size: 20 # 最大线…...