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

C++11新特性【下】{lambda表达式、可变模板参数、包装器}

一、lambda表达式

在C++98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法。如果待排序元素为自定义类型,需要用户定义排序时的比较规则,随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法, 都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名, 这些都给编程者带来了极大的不便。因此,在C++11语法中出现了Lambda表达式。

1.1 lambda表达式语法:

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement }

lambda表达式各部分说明
  • [capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[ ]来 判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda 函数使用。
  • (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略
  • mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  • ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
  • {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获 到的变量。

注意:

在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。

int main()
{//lambda实现两数相加auto add = [](int a, int b) {return a + b; };cout << add(1, 2) << endl;//lambda实现swapauto swap = [](int& a, int& b){int temp = a;a = b;b = temp;};
}
捕获列表说明:

捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。

  • [var]:表示值传递方式捕捉变量var
  • [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
  • [&var]:表示引用传递捕捉变量var
  • [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
  • [this]:表示值传递方式捕捉当前的this指针

捕捉列表还可以混合捕捉:

	int a = 1;int b = 2;int c = 3;int d = 4;//除了a b传值捕捉外,其他的变量都是引用捕捉auto func = [&, a, b]() mutable{a++;b++;c++;d++;};func();cout << a << " " << b <<" " << c << " " << d << " " << endl;// 1 2 4 5

注意:

  • 父作用域指包含lambda函数的语句块
  • 捕捉列表不允许变量重复传递,否则就会导致编译错误。比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
  • 在块作用域以外的lambda函数捕捉列表必须为空。
  • 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错。
  • lambda表达式之间不能相互赋值,即使看起来类型相同

ps:lambda表达式的类型不是直接由语言定义的具名类型,而是编译器为每一个lambda表达式生成的唯一的、匿名的非联合类类型(non-union class type)。这个类型没有名字,因此你不能用它来直接声明变量或作为函数的参数类型。但是,你可以通过auto关键字或者模板来间接地引用这个类型。即使两个表达式的内容完全相同,其类型都是不一样的

1.2 函数对象与lambda表达式

函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了operator()运算符的 类对象。

class Rate
{
public:Rate(double rate) : _rate(rate){}double operator()(double money, int year){return money * _rate * year;}
private:double _rate;
};
int main()
{// 函数对象double rate = 0.49;Rate r1(rate);r1(10000, 2);// lamberauto r2 = [=](double monty, int year)->double {return monty * rate * year;};r2(10000, 2);return 0;
}

从使用方式上来看,函数对象与lambda表达式完全一样。 函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可 以直接将该变量捕获到。

实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如 果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。

二、新的类功能

默认成员函数

原来C++类中,有6个默认成员函数:

  1. 构造函数
  2. 析构函数
  3. 拷贝构造函数
  4. 拷贝赋值重载
  5. 取地址重载
  6. const 取地址重载

最后重要的是前4个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。 C++11 新增了两个:移动构造函数和移动赋值运算符重载。

针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:

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

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

class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p):_name(p._name),_age(p._age){}Person(Person&& p) = default;private:bit::string _name;int _age;
};int main()
{Person s1;Person s2 = s1;Person s3 = std::move(s1);return 0;
}
禁止生成默认函数的关键字delete:

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

class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p) = delete;
private:bit::string _name;int _age;
};
int main()
{Person s1;Person s2 = s1;Person s3 = std::move(s1);return 0;
}

三、可变模版参数

C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,相比 C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改 进。由于可变模版参数比较抽象难懂,本篇博客主要讲解其基本特性和使用方法

下面就是一个基本可变参数的函数模板:

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数 包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的, 只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特 点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变参数,所以我们的用一些奇招来一一获取参数包的值。

递归函数方式展开参数包
template<class T>
void _Show_list(const T& val)
{cout << val<<endl;
}template<class T,class ...Args>
void _Show_list(T val,Args... args)
{cout << val << " ";_Show_list(args...);
}template<class ...Args>
void Show_list(Args... args)
{_Show_list(args...);
}int main()
{Show_list(1);Show_list(1,"abc");Show_list(1,"abc",2.2);return 0;
}

底层解释:

逗号表达式展开参数包

这种展开参数包的方式,不需要通过递归终止函数,是直接在expand函数体中展开的, printarg 不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式 实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。 expand函数中的逗号表达式:(printarg(args), 0),也是按照这个执行顺序,先执行 printarg(args),再得到逗号表达式的结果0。同时还用到了C++11的另外一个特性——初始化列 表,通过初始化列表来初始化一个变长数组, {(printarg(args), 0)...}将会展开成((printarg(arg1),0), (printarg(arg2),0), (printarg(arg3),0), etc... ),最终会创建一个元素值都为0的数组int arr[sizeof... (Args)]。由于是逗号表达式,在创建数组的过程中会先执行逗号表达式前面的部分printarg(args) 打印出参数,也就是说在构造int数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在 数组构造的过程展开参数包

template<class T>
void print(const T& val)
{cout << val << " ";
}template<class ...Args>
void Show_list(Args... args)
{int arr[] = { (print(args),0)... };cout << endl;
}int main()
{Show_list(1,"abc",2.2);return 0;
}
STL容器中的empalce相关接口函数:
template <class... Args>
void emplace_back (Args&&... args);

可见emplace系列使用了可变模版参数和万能引用,相比于emplace系列,push_back的参数存在左值引用和右值引用两个版本,那emplace与push_back有什么区别吗?

如果插入的数据是一个对象的话,不论是传左值还是传右值,两者的效率是一摸一样的:

emplace系列函数可以直接传构造对象的参数包,该参数包会一直往下传,到最底层时直接构造,相比于push_back传右值来说省了一次移动构造的消耗

总结:

1.对于深拷贝的类,push_back传右值和emplace传构造对象的参数包来说,效率差不多,因为对于深拷贝来说,多一次数据交换的影响不大

2.对于浅拷贝的类来说,push_back传右值要经历构造和拷贝构造,emplace传构造对象的参数包仅一次构造,此时效率提升比较大

3.推荐用emplace系列函数代替push和insert系列函数,此外emplace系列函数能传参数包就传参数包

四、包装器

function包装器

对于可调用对象一般有三种:函数指针、仿函数、lambda表达式,function包装器 也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。包装器一般就是包装这三种类型的。

std::function在头文件<functional>// 类模板原型如下
template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参
包装器的使用
// 使用方法如下:
#include <functional>
int f(int a, int b)
{return a + b;
}
struct Functor
{
public:int operator() (int a, int b){return a + b;}
};
class Plus
{
public:static int plusi(int a, int b){return a + b;}double plusd(double a, double b){return a + b;}
};
int main()
{// 函数名(函数指针)std::function<int(int, int)> func1 = f;cout << func1(1, 2) << endl;// 函数对象std::function<int(int, int)> func2 = Functor();cout << func2(1, 2) << endl;// lamber表达式std::function<int(int, int)> func3 = [](const int a, const int b){return a + b; };cout << func3(1, 2) << endl;// 类的成员函数std::function<int(int, int)> func4 = &Plus::plusi;cout << func4(1, 2) << endl;std::function<double(Plus, double, double)> func5 = &Plus::plusd;cout << func5(Plus(), 1.1, 2.2) << endl;std::function<double(Plus*, double, double)> func6 = &Plus::plusd;Plus plus;cout << func6(&plus, 1.1, 2.2) << endl;return 0;
}
注意:

包装器也可以包装类成员函数,不过要添加函数所属类域,在c++中一般还要在类名前加一个&,对于静态成员函数,按照函数声明传参即可,对于非静态成员函数,要注意函数存在一个隐藏的this指针,我们可以传一个对象,也可以传一个对象的地址,底层会根据这个对象或者地址从而找到这个函数

包装器的意义
#include<iostream>
using namespace std;template<class F, class T>
T useF(F f, T x)
{static int count = 0;cout << "count:" << ++count << endl;cout << "count:" << &count << endl;return f(x);
}double f(double i)
{return i / 2;
}struct Functor
{double operator()(double d){return d / 3;}
};int main()
{// 函数名cout << useF(f, 11.11) << endl;cout << endl;// 函数对象cout << useF(Functor(), 11.11) << endl;cout << endl;// lamber表达式cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;cout << endl;return 0;
}

通过上面的程序验证,我们会发现useF函数模板实例化了三份,如此丰富的可调用类型,可能会导致模板的效率低下。而包装器就可以很好的解决上述问题。

int main()
{// 函数名std::function<double(double)> func1 = f;cout << useF(func1, 11.11) << endl;cout << endl;// 函数对象std::function<double(double)> func2 = Functor();cout << useF(func2, 11.11) << endl;cout << endl;// lamber表达式std::function<double(double)> func3 = [](double d)->double { return d /4; };cout << useF(func3, 11.11) << endl;cout << endl;return 0;
}

这样useF就仅实例化出一份,比较节省空间

bind绑定

std::bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器),接受一个可 调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。一般而 言,我们用它可以把一个原本接收N个参数的函数fn,通过绑定一些参数,返回一个接收M个(M 可以大于N,但这么做没什么意义)参数的新函数。同时,使用std::bind函数还可以实现参数顺 序调整等操作。

// 原型如下:
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);// with return type (2) 
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);

可以将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对 象来“适应”原对象的参数列表。 调用bind的一般形式:auto newCallable = bind(callable,arg_list); 其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的 callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中 的参数。

通过bind改变函数的参数顺序

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

通过bind改变函数的传参个数
void func(string s, int a, int b)
{cout << s << " " << a << " " << b << endl;
}int main()
{auto f1 = bind(func,"abc" ,placeholders::_1, placeholders::_2);f1(1, 2);auto f2 = bind(func, placeholders::_1,666, placeholders::_2);f2("def", 1);
}结果:
//abc 1 2
//def 666 1

相关文章:

C++11新特性【下】{lambda表达式、可变模板参数、包装器}

一、lambda表达式 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。如果待排序元素为自定义类型&#xff0c;需要用户定义排序时的比较规则&#xff0c;随着C语法的发展&#xff0c;人们开始觉得上面的写法太复杂了&#xff0c…...

SpringBoot使用手册

SpringBoot使用手册 1、自动装配 1.1、创建spring Boot项目 在之前的文章中已经专门写过&#xff0c;这里不做赘述。 1.2、pom.xml 1.2.1、版本管理 在学习完maven项目后&#xff0c;我们学习框架时首先阅读的就是pom.xml文件&#xff0c;这里是管理自己该项目中所用到的…...

HTML CSS 基础复习笔记 - 列表使用

用于自己复习 自定义列表 示例代码 <!DOCTYPE html> <html> <head><title>Definition List Example</title> </head> <body><h1>古诗</h1><dl><dt>静夜思</dt><dd>床前明月光&#xff0c;疑…...

017-GeoGebra基础篇-微积分函数求解圆弧面积问题

基础篇慢慢的走进尾声&#xff0c;今天给大家带来一个小项目&#xff0c;是关于高中数学微积分部分的展示&#xff0c;这个项目主要包含了函数的介绍、函数与图形绘制的区别、区域函数图像的绘制、积分函数的应用、动态文本的调用、嵌套滑动条的应用等等&#xff0c;以及其他常…...

Element中的选择器组件Select (一级选择组件el-select)

简述&#xff1a;在 Element UI 中&#xff0c;ElSelect&#xff08;或简称为 Select&#xff09;是一个非常常用的选择器组件&#xff0c;它提供了丰富的功能来帮助用户从一组预定义的选项中选择一个或多个值。这里来简单记录一下 一. 组件和属性配置 <el-selectv-model&q…...

数值分析笔记(五)线性方程组解法

三角分解法 A的杜利特分解公式如下&#xff1a; u 1 j a 1 j ( j 1 , 2 , ⋯ , n ) , l i 1 a i 1 / u 11 ( i 2 , 3 , ⋯ , n ) , u k j a k j − ∑ m 1 k − 1 l b m u m j ⇒ a k j ( j k , k 1 , ⋯ , n ) , l i k ( a i k − ∑ m 1 k − 1 l i n u m k ) /…...

IDEA中Maven的配置

目录 1. 安装maven 2. 配置环境变量 3. IDEA中配置Maven 4. 配置仓库目录 1. 安装maven 官网下载地址&#xff1a;Maven – Download Apache Maven 下载后&#xff0c;将zip压缩包解压到某个目录即可。 2. 配置环境变量 变量名称随意&#xff0c;通常为M2_HOME&#xff…...

成人高考本科何时报名-深职训学校帮您规划学习之路

你有想过继续深造自己的学历吗&#xff1f;也许你已经工作多年&#xff0c;但总觉得学历是一块心病&#xff0c;想要通过成人高考本科来提升自己。不用着急&#xff0c;今天我们来聊一聊成人高考本科的报名时间&#xff0c;以及深职训学校如何帮助你顺利完成报名。 深圳成人高…...

C++ STL 协程(Coroutines)

一:什么是协程(Coroutines): 协程是轻量级线程,可以暂停和恢复执行,协程拥有自己的暂停点状态,协程暂停时,将当前状态保存起来,在恢复执行时会恢复之前保存的状态。 二:例子: #include <coroutine> #include <iostream>void doTheWork() {std::cout <…...

虚拟机下基于海思移植QT(一)——虚拟机下安装QT

0.参考资料 1.海思Hi3516DV300 移植Qt 运行并在HDMI显示器上显示 2.搭建海思3559A-Qt4.8.7Openssl开发环境 1.报错解决 通过下面命令查询 strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC_通过命令行没有解决&#xff1a; sudo apt install libc6-dev libc6参考解决…...

计算机网络部分知识点整理

停止等待协议的窗口尺寸为 1。 √以太网标准是IEEE802.3TCP/IP四层&#xff0c;OSI模型有7层&#xff0c;地址解析协议 ARP 在 OSI 参考七层协议属于数据链路层&#xff0c;在TCP/IP 协议属于网络层&#xff0c;ARP作用&#xff1a;将 IP 地址映射到第二层地址&#xff0c;交换…...

【Qt】Qt概述

目录 一. 什么是Qt 二. Qt的优势 三. Qt的应用场景 四. Qt行业发展方向 一. 什么是Qt Qt是一个跨平台的C图形用户界面应用程序框架&#xff0c;为应用程序开发者提供了建立艺术级图形界面所需的所有功能。 Qt是完全面向对象的&#xff0c;很容易扩展&#xff0c;同时Qt为开发…...

读书笔记-《魔鬼经济学》

这是一本非常有意思的经济学启蒙书&#xff0c;作者探讨了许多问题&#xff0c;并通过数据找到答案。 我们先来看看作者眼中的“魔鬼经济学”是什么&#xff0c;再选一个贴近我们生活的例子进行阐述。 01 魔鬼经济学 中心思想&#xff1a;假如道德代表人类对世界运转方式的期…...

2024.7.7总结

今天是惊心动魄的一天&#xff0c;记录一下吧! 昨天晚上害怕早上闹铃响了听不到&#xff0c;担心有意外出现&#xff0c;错过回家的车票&#xff0c;于是便在晚上设置了3个闹铃&#xff0c;6:50&#xff0c;7:00&#xff0c;7:05然后也关了静音。没想到&#xff0c;早上按照正…...

uniapp做小程序内打开地图展示位置信息

使用场景&#xff1a;项目中需要通过位置信息打开地图查看当前位置信息在地图那个位置&#xff0c;每个酒店有自己的经纬度和详细地址&#xff0c;点击地图按钮打开内置地图如图 方法如下&#xff1a; <view class"dttu" click"openMap(info.locationY,info.…...

leetcode 283.移动零

leetcode 283.移动零 自己刷题并且进行记录一下 题解 c class Solution { public:void moveZeroes(vector<int>& nums) {int count 0;for (int i 0; i < nums.size(); i) {if(nums[i] ! 0) {nums[count] nums[i];if (count !i) {nums[i] 0;}count;}}} };...

Unity | Shader基础知识(第十七集:学习Stencil并做出透视效果)

目录 一、前言 二、了解unity预制的材质 三、什么是Stencil 四、UGUI如何使用Stencil&#xff08;无代码&#xff09; 1.Canvas中Image使用Stencil制作透视效果 2.学习Stencil 3.分析透视效果的需求 五、模型如何使用Stencil 1.shader准备 2.渲染顺序 3.Stencil代码语…...

【3D->2D转换(1)】LSS(提升,投放,捕捉)

Lift, Splat, Shoot 这是一个端到端架构&#xff0c;直接从任意数量的摄像头数据提取给定图像场景的鸟瞰图表示。将每个图像分别“提升&#xff08;lift&#xff09;”到每个摄像头的视锥&#xff08;frustum&#xff09;&#xff0c;然后将所有视锥“投放&#xff08;splat&a…...

MyBatis 框架核心及面试知识要点

1、什么是 MyBatis? MyBatis 是一款优秀的支持自定义 SQL 查询、存储过程和高级映射的持久层框架&#xff0c;消除了 几乎所有的 JDBC 代码和参数的手动设置以及结果集的检索 。 MyBatis 可以使用 XML,或注解进 行配置和映射&#xff0c;MyBatis 通过将参数映射到配置的 SOL,形…...

《linux系统内核设计与实现》-实现最简单的字符设备驱动

开发linux内核驱动需要以下4个步骤&#xff1a; 1 编写hello驱动代码 驱动代码如下 helloDev.c&#xff0c;这是一个最小、最简单的驱动&#xff0c;去掉了其他的不相干代码&#xff0c;尽量让大家能了解驱动本身。 #include <linux/module.h> #include <linux/mod…...

【MotionCap】pycharm 远程在wsl2 ubuntu20.04中root的miniconda3环境

pycharm wsl2 链接到pycharmsbin 都能看到内容,/root 下内容赋予了zhangbin 所有,pycharm还是看不到/root 下内容。sudo 安装了miniconda3 引发了这些问题 由于是在 root 用户安装的miniconda3 所以安装路径在/root/miniconda3 里 这导致了环境也是root用户的,会触发告警 WA…...

[BJDCTF 2nd]简单注入

sqlsqlsqlsqlsql又来喽 过滤了单双引号&#xff0c;等于符号&#xff0c;还有select等&#xff0c;但是这里没有二次注入 。扫描发现hint.txt 看出题人的意思是&#xff0c;得到密码即可获得flag。 select * from users where username$_POST["username"] and passw…...

java项目的一些功能(完善登录功能、注册接口参数校验、完善分页查询、完善日期格式、更新文章分类和添加文章分类的分组校验、自定义校验、文件上传 )

目录 完善登录功能 注册接口参数校验 完善分页查询 完善日期格式 更新文章分类和添加文章分类的分组校验 ​编辑 自定义校验 文件上传 完善登录功能 对前端传过来的明文密码进行md5加密处理 password DigestUtils.md5DigestAsHex(password.getBytes()); 这样既可 注…...

Mac安装AndroidStudio连接手机 客户端测试

参考文档&#xff1a;https://www.cnblogs.com/andy0816/p/17097760.html 环境依赖 需要java 1.8 java安装 略 下载Android Studio 地址 下载 Android Studio 和应用工具 - Android 开发者 | Android Developers 本机对应的包进行下载 安装过程 https://www.cnblogs.c…...

Git 完整的提交规范教程

约定式提交规范 本文中的关键词 “必须&#xff08;MUST&#xff09;”、“禁止&#xff08;MUST NOT&#xff09;”、“必要&#xff08;REQUIRED&#xff09;”、“应当&#xff08;SHALL&#xff09;”、“不应当&#xff08;SHALL NOT&#xff09;”、“应该&#xff08;S…...

【TB作品】51单片机 Proteus仿真 00001仿真实物PID电机调速系统

实验报告&#xff1a;Proteus 仿真 PID 电机调速系统 一、实验背景 PID&#xff08;比例-积分-微分&#xff09;控制器广泛应用于工业控制系统中&#xff0c;用于调节各种物理变量。本实验的目的是通过 Proteus 仿真软件设计并实现一个 PID 电机调速系统&#xff0c;以控制直…...

【LInux】从动态库的加载深入理解页表机制

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

IDEA与通义灵码的智能编程之旅

1 概述 本文主要介绍在IDEA中如何安装和使用通义灵码来助力软件编程,从而提高编程效率,创造更大的个人同企业价值。 2 安装通义灵码 2.1 打开IDEA插件市场 点击IDEA的设置按钮,下拉选择Plugins,如下: 2.2 搜索通义灵码 在搜索框中输入“通义灵码”,如下: 2.3 安…...

多表查询sql

概述&#xff1a;项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系&#xff0c;分为三种&#xff1a; 一对多多对多一对一 一、多表关系 一对多 案例&#xff1a;部门与…...

移动端UI风格营造舒适氛围

移动端UI风格营造舒适氛围...

摸鱼大数据——Spark SQL——DataFrame详解一

1.DataFrame基本介绍 DataFrame表示的是一个二维的表。二维表&#xff0c;必然存在行、列等表结构描述信息​表结构描述信息(元数据Schema): StructType对象字段: StructField对象&#xff0c;可以描述字段名称、字段数据类型、是否可以为空行: Row对象列: Column对象&#xff…...

【Java探索之旅】初识多态_概念_实现条件

文章目录 &#x1f4d1;前言一、多态1.1 概念1.2 多态的实现条件 &#x1f324;️全篇总结 &#x1f4d1;前言 多态作为面向对象编程中的重要概念&#xff0c;为我们提供了一种灵活而强大的编程方式。通过多态&#xff0c;同一种操作可以应用于不同的对象&#xff0c;并根据对象…...

[Day 26] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

數據科學與AI的整合應用 數據科學&#xff08;Data Science&#xff09;和人工智能&#xff08;AI&#xff09;在現代技術世界中扮演著至關重要的角色。兩者的整合應用能夠為企業和研究人員提供強大的工具&#xff0c;以更好地理解、預測和解決各種複雜的問題。本文將深入探討…...

算法 —— 滑动窗口

目录 长度最小的子数组 无重复字符的最长子串 最大连续1的个数 将x减到0的最小操作数 找到字符串中所有字母异位词 最小覆盖子串 长度最小的子数组 sum比target小就进窗口&#xff0c;sum比target大就出窗口&#xff0c;由于数组是正数&#xff0c;所以相加会使sum变大&…...

【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)

文章目录 定义简单工厂模式案例 | 代码Phone顶层接口设计Meizu品牌类Xiaomi品牌类PhoneFactory工厂类Customer 消费者类 工厂方法模式案例 | 代码PhoneFactory工厂类 Java高级特性---工厂模式与反射的高阶玩法方案&#xff1a;反射工厂模式 总结 其实工厂模式就是用一个代理类帮…...

Linux之计划和日志

计划任务 计划任务概念解析 在Linux操作系统中,除了用户即时执行的命令操作以外,还可以配置在指定的时间、指定的日期执行预先计划好的系统管理任务(如定期备份、定期采集监测数据)。通过安装at和crontabs这两个系统服务实现一次性、周期性计划任务的功能,并分别通过at、…...

C++ 多态篇

文章目录 1. 多态的概念和实现1.1 概念1.2 实现1.2.1 协变1.2.2 析构函数1.2.3 子类虚函数不加virtual 2. C11 final和override3.1 final3.2 override 3. 函数重载、重写与隐藏4. 多态的原理5. 抽象类6.单继承和多继承的虚表6.1 单继承6.2 多继承 7. 菱形继承的虚表(了解)7.1 菱…...

【LVGL-SquareLine Studio】

LVGL-SquareLine Studio ■ SquareLine Studio-官网下载地址■ SquareLine Studio-参考博客■ SquareLine Studio-安装■ SquareLine Studio-汉化■ SquareLine Studio-■ SquareLine Studio-■ SquareLine Studio-■ SquareLine Studio-■ SquareLine Studio- ■ SquareLine S…...

mysqli 与mysql 区别和联系, 举例说明

mysqli是一种PHP的扩展&#xff0c;用于与MySQL数据库进行交互。它提供了一套面向对象的接口&#xff0c;可以更方便地操作数据库。MySQL是一种关系型数据库管理系统&#xff0c;用于存储和管理数据。 区别&#xff1a; mysqli是MySQL的扩展&#xff0c;而不是单独的数据库管…...

【SpringCloud应用框架】Nacos安装和服务提供者注册

第二章 Spring Cloud Alibaba Nacos之Nacos安装和服务提供者注册 文章目录 Nacos介绍为何使用Nacos&#xff1f;一、Nacos下载和安装1. 下载2. 安装Linux/Unix/MacWindows 二、Nacos服务提供者注册1. Nacos代替Eureka2. Nacos服务注册中心3. 引入Nacos Discovery进行服务注册/发…...

英语学习交流小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;每日打卡管理&#xff0c;备忘录管理&#xff0c;学习计划管理&#xff0c;学习资源管理&#xff0c;论坛交流 微信端账号功能包括&#xff1a;系统首页&#xff0c;学习资源&…...

实现Java多线程中的线程间通信

实现Java多线程中的线程间通信 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. 线程间通信的基本概念 在线程编程中&#xff0c;线程间通信是指多个线程之间通过共享内存或消息传递的方式进行交…...

C++模板元编程(一)——可变参数模板

这个系列主要记录C模板元编程的常用语法 文章目录 引言语法应用函数模板可变参数的打印可变参数的最小/最大函数 类模板 参考文献 引言 在C11之前&#xff0c;函数模板和类模板只支持含有固定数量的模板参数。C11增强了模板功能&#xff0c;允许模板定义中包含任意个(包括0个)…...

kafka中

Kafka RocketMQ概述 RabbitMQ概述 ActiveMQ概述 ZeroMQ概述 MQ对比选型 适用场景-从公司基础建设力量角度出发 适用场景-从业务场景出发 Kafka配置介绍 运行Kafka 安装ELAK 配置EFAK EFAK界面 KAFKA常用术语 Kafka常用指令 Kafka中消息读取 单播消息 group.id 相同 多播消息 g…...

Android 获取当前电池状态

在 API 级别 23 上获取充电状态 要在 API 级别 23 上获取电池的当前状态&#xff0c;只需使用电池管理器系统服务&#xff1a; BatteryManager batteryManager (BatteryManager) getSystemService(BATTERY_SERVICE); boolean isCharging batteryManager.isCharging();使用 S…...

【JVM 的内存模型】

1. JVM内存模型 下图为JVM内存结构模型&#xff1a; 两种执行方式&#xff1a; 解释执行&#xff1a;JVM是由C语言编写的&#xff0c;其中有C解释器&#xff0c;负责先将Java语言解释翻译为C语言。缺点是经过一次JVM翻译&#xff0c;速度慢一点。JIT执行&#xff1a;JIT编译器…...

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【17】认证服务01—短信/邮件/异常/MD5

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【17】认证服务01 环境搭建验证码倒计时短信服务邮件服务验证码短信形式&#xff1a;邮件形式&#xff1a; 异常机制MD5参考 环境搭建 C:\Windows\System32\drivers\etc\hosts 192.168.…...

geom buffer制作

1. auto buffer_geom line_string->buffer(15);//buffer //这个是x和y各扩大段15个单位 auto buffer_geom line_string->buffer(15);//buffer //这个是x和y各扩大段15米 获取buffer坐标 auto boundary buffer_geom->getBoundary(); auto boundary_coords boun…...

微软正在放弃React

最近&#xff0c;微软Edge团队撰写了一篇文章&#xff0c;介绍了微软团队如何努力提升Edge浏览器的性能。但在文中&#xff0c;微软对React提出了批评&#xff0c;并宣布他们将不再在Edge浏览器的开发中使用React。 我将详细解析他们的整篇文章内容&#xff0c;探讨这一决定对…...

U盘非安全退出后的格式化危机与高效恢复策略

在数字化时代&#xff0c;U盘作为数据存储与传输的重要工具&#xff0c;其数据安全备受关注。然而&#xff0c;一个常见的操作失误——U盘没有安全退出便直接拔出&#xff0c;随后再插入时却遭遇“需要格式化”的提示&#xff0c;这不仅让用户措手不及&#xff0c;更可能意味着…...