【C++11】右值引用和移动语义:万字总结
📝前言:
这篇文章我们来讲讲右值引用和移动语义
🎬个人简介:努力学习ing
📋个人专栏:C++学习笔记
🎀CSDN主页 愚润求学
🌄其他专栏:C语言入门基础,python入门基础,python刷题专栏,Linux
文章目录
- 一,左值和右值
- 二,左值引用和右值引用
- 1 对比异同
- 2 延长生命周期
- 3 参数匹配
- 三,右值引用和移动语义
- 1 左值引用主要使用场景
- 2 移动构造和移动赋值
- 3 不同优化下的拷贝构造优化效果
- 没有优化
- 优化1
- 优化2
- 4 不同优化下的拷贝赋值优化效果
- 没有优化
- 优化1
- 优化2
- 5 总结及移动语义的重要性
- 四,类型分类
- 五,引用折叠
- 六,完美转发
一,左值和右值
左值和右值最重要的区别:能不能取地址,能取地址的是左值,不能的是右值!
左值:
- 左值:一个表示数据的表达式,是一个具名的、有明确内存地址的对象,如:变量名,解引用的指针
- 可以出现在赋值符号的左边,也可以出现在右边。(如果有
const
修饰,就无法修改,但是可以取地址)
右值:
- 右值:也是⼀个表示数据的表达式,常见的有:字面量,表达式返回时生成的临时变量,函数传值返回时的临时变量,你们对象…
- 不能出现在赋值符号的左边,不能取地址
示例:
常见左值,可以在=
左边,可以取地址:
int* p = new int(0);int a = 10;const int c = a;*p = 10;string s{ "111111" };s[0] = 'x'; // 函数返回值为引用,也是左值
常见右值,不能在=
左边,不能取地址:
10; // 字面量x + y; // 表达式返回中间生成临时变量fmin(x, y); // 传值返回中间生成临时变量string("11111"); // 匿名对象(具有常性)
二,左值引用和右值引用
1 对比异同
相同点:
- 左值引用是给左值取别名,右值引用是给右值取别名,语法层面都不开空间
- 从底层汇编上看,都是用指针实现的
不同点:
左值引用:
- 语法:
Type &r1 = x;
,x
是左值 const
左值引⽤可以引用右值
右值引用:
- 语法:
Type &&rr1 = y;
,y
是右值 - 右值引用可以引用
move(左值)
(move
本质内部是进行强制类型转换,但是不改变原来变量的属性【这个属性指:左值 / 右值】) - 右值引用本身是左值,即:在上面的语法中:
rr1
是左值
示例:
左值引用:
// 左值引用
int& ra = a;
const int& rc = c;
string& rs = s;
const int& rc = 10; // const左值引用 引用右值
右值引用:
const int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
string&& rr4 = string("11111");
string&& rr5 = move(s); // 引用move(左值)
double&& rr6 = move(rr2); // rr2是右值引用,属性是左值,要使用move才能被右值引用
2 延长生命周期
右值引用和const
左值引用,可以延长临时变量/匿名对象的生命周期(普通的左值引用不行,因为临时变量具有常性)
示例:
double x = 1.1, y = 2.2;
// double& r1 = x + y; 报错:无法从“double”转换为“double &
const double& rr2 = x + y;
double&& rr3 = x + y;
rr3++; // 并且非 const 的右值引用可以修改
说明:x+y
表达式计算的结果会先储存在临时变量中(这个临时变量存储在这个表达式所在的栈帧中),但是生命周期只有这一行。使用右值引用和const
左值引用以后可以延长这个临时变量的生命周期,即:这一行结束以后不销毁,而是跟着rr2
/ rr3
3 参数匹配
- 对于不同的引用类型,以及带
const
和非const
,都属于不同的类型,可以构成函数重载 - 根据实参传入的类型不同,编译器会选择最匹配的函数
const
左值引用作为参数的函数,实参传递左值和右值都可以匹配
示例:
void f(int& x)
{cout << "左值引用重载 f(" << x << ")\n";
}
void f(const int& x)
{cout << "到 const 的左值引用重载 f(" << x << ")\n";
}
void f(int&& x)
{cout << "右值引用重载 f(" << x << ")\n";
}int main()
{int i = 1;const int ci = 2;f(i); // 调用 f(int&)f(ci); // 调用 f(const int&)f(3); // 调用 f(int&&),如果没有 f(int&&) 重载,则会调用 f(const int&)f(std::move(i)); // 调用 f(int&&)// 右值引用变量在用于表达式时是左值int&& x = 1;f(x); // 调用 f(int& x)f(std::move(x)); // 调用 f(int&& x)return 0;
}
运行结果:
三,右值引用和移动语义
1 左值引用主要使用场景
我们都知道:函数传值传参、函数传值返回、以及表达式计算结果后赋值…都需要先把原来的数据拷贝给临时变量,然后再由临时变量拷贝回给接收值。这样的效率是非常低的。
之前,我们为了减少这种拷贝就已经开始运用左值引用了,如:
- 使用cosnt 左值引用作为形参(直接使用别名,减少传值的拷贝)
- 使用左值引用作为函数返回值
但是,当函数内部,返回的是局部变量且函数结束后要被销毁时,我们无法通过左值引用来接收。
错误示例(注意如果要进行测试:这里是string
不要用库里面的,因为库里面的已经实现了移动构造和移动赋值):
const tr::string& addStrings(tr::string num1, tr::string num2) {tr::string str;int end1 = num1.size() - 1, end2 = num2.size() - 1;// 进位int next = 0;while (end1 >= 0 || end2 >= 0){int val1 = end1 >= 0 ? num1[end1--] - '0' : 0;int val2 = end2 >= 0 ? num2[end2--] - '0' : 0;int ret = val1 + val2 + next;next = ret / 10;ret = ret % 10;str += ('0' + ret);}if (next == 1)str += '1';reverse(str.begin(), str.end());return str;
}int main()
{tr::string num1{ "2222222222" };tr::string num2{ "1111111111" };tr::string num3 = addStrings(num1, num2);
}
代码为 -1073741819 (0xc0000005)
程序会崩掉,为什么呢?
因为,在addStrings
函数里面,str
是一个局部对象,即使被引用绑定了,但是函数结束后,存储str
的栈帧被销毁,str
也会被销毁(无法达到延长生命周期的效果)
那难道就没有解决方法了吗?有的兄弟,有的!
在C++11之前,可以通过传输出型参数解决:
// 输出型参数
void addStrings(tr::string num1, tr::string num2, tr::string& num3) {int end1 = num1.size() - 1, end2 = num2.size() - 1;// 进位int next = 0;while (end1 >= 0 || end2 >= 0){int val1 = end1 >= 0 ? num1[end1--] - '0' : 0;int val2 = end2 >= 0 ? num2[end2--] - '0' : 0;int ret = val1 + val2 + next;next = ret / 10;ret = ret % 10;num3 += ('0' + ret);}if (next == 1)num3 += '1';reverse(num3.begin(), num3.end());
}int main()
{tr::string num1{ "2222222222" };tr::string num2{ "1111111111" };tr::string num3;addStrings(num1, num2, num3);cout << num3.c_str() << endl;
}
说明:
num3
就是输出型参数,形参为num3
的引用,直接在函数内部修改num3
。但是这样的做法牺牲了一定的可读性。
还有其他做法吗?
有的兄弟,有的,那就是C++11的右值引用+移动语义!
2 移动构造和移动赋值
首先,我们先来讲讲移动构造和移动赋值的语法和写法:
- 移动构造:是⼀种构造函数,类似拷贝构造函数。要求第⼀个参数是该类类型的右值引用,如果还有其他参数,额外的参数必须有缺省值
- 移动赋值:是⼀个赋值运算符的重载,他跟拷贝赋值构成函数重载。移动赋值函数要求第⼀个参数是该类类型的右值引用。它们两个的关系就类似移动构造和拷贝构造的关系。
话不多说,直接上代码理解:
我们先看一个普通的拷贝构造:
string(const string& s):_str(nullptr)
{// cout << "string(const string& s) -- 拷贝构造" << endl;reserve(s._capacity);for (auto ch : s){push_back(ch);}
}
再看移动构造和移动赋值:
// 移动构造
string(string&& s)
{cout << "string(string&& s) -- 移动构造" << endl;swap(s);
}
// 移动赋值
string& operator=(string&& s)
{cout << "string& operator=(string&& s) -- 移动赋值" << endl;swap(s);return *this;
}
说明:
在这里,s
是一个将要销毁的右值,直接swap
把s
的资源交换给了this
(这里的代价比拷贝构造小的多,可能只是一个指针的交换等),然后s
带着原来刚初始化的this
的资源被销毁。
3 不同优化下的拷贝构造优化效果
首先我们要理解,什么时候,拷贝构造会被使用?
没有优化
当没有任何优化的情况下:
但是这里我调不出来,现在的编译器都优化的太好了。
优化1
优化版本1:
省掉临时变量,直接用str
构造num3
,{"1111111111"}
这是同理,省掉了临时变量。
我们可以在Linux下用g++编译器来观察:g++ test.cpp -fno-elide-constructors
(看别人都说:这是取消所有优化,但是我测试的效果任然是保留了这优化1的效果的)
测试结果:
说明:
- 前两个构造分别对应:用
{"1111111111"}
和{"2222222222"}
来构造num1
和num2
。优化掉了中间的临时变量:没有优化时是:先用{"1111111111"}
构造临时变量,然后再用临时变量拷贝构造num1
- 第三个构造是定义函数内
str
的时候的构造(即函数内第一条语句) - 第四个拷贝构造,就是优化1 的效果,直接省掉了临时变量,用
str
直接拷贝构造num3
优化2
新版编译器都是到了优化2的程度:
运行效果:
说明:
- 前两个和优化1 一样,不解释了
- 可见这里少了一个拷贝构造:编译器直接优化成:用把
str
当num3
的引用了,在函数内部直接就改了num3
,减少了拷贝
4 不同优化下的拷贝赋值优化效果
刚刚我们看到了编译器的超强优化,大大避免了拷贝的出现。但是,能优化所有情况吗?答案是否定的,当出现拷贝赋值的时候,编译器不敢优化用临时变量拷贝赋值的那一步。
我们把代码改成这样:
tr::string num3;
num3 = addStrings({ "1111111111" }, { "2222222222" });
没有优化
如果没有优化:
优化1
优化1:
没错,你没看错,和没有优化的效果是一样的,只是在传参那里会优化掉临时变量,但是传值返回并调用拷贝赋值这里一点也不会省
我们在Linux下运行优化1的效果:
说明:
- 前四个构造分别对应:add外部
num3
,{"1111111111"}
,{"2222222222"}
,add内部str
- 拷贝构造:用返回值
str
拷贝构造临时对象 - 拷贝赋值:用临时对象拷贝赋值外部的
num3
优化2
优化2以后:
优化掉了,用str
拷贝构造临时对象这一步(可以理解为,这时候str
就是临时对象的引用)
但是,即使最大优化:临时对象到拷贝赋值这一步也不能省
我们在优化2的情况下运行代码,运行结果:
5 总结及移动语义的重要性
通过上面的优化我们可以发现:
在最强优化的情况下,如果只有构造操作,则两个拷贝构造会被直接优化掉。但是,如果是构造+赋值操作,则最多只能把拷贝构造给优化掉(即:和构造合并),但是用临时变量来拷贝赋值这一步无法优化。
所以这时候,右值引用+移动语义的意义就非常大了。因为移动构造和移动赋值的代价都特别小。
当我们实现了移动构造和移动赋值以后,对应的拷贝构造和拷贝赋值就会被替换成我们的移动构造和移动赋值。
示例(优化1 下:构造 + 赋值运行结果)
示例(优化2 下:构造 + 赋值运行结果):
移动构造和移动赋值的使用场景:
对于像string/vector
这样的深拷贝的类或者包含深拷贝的成员变量的类,移动构造和移动赋值才有
意义,因为移动构造和移动赋值的第⼀个参数都是右值引用的类型,他的本质是要“窃取”引用的
右值对象的资源,而不是像拷贝构造和拷贝赋值那样去拷贝资源,从提高效率
在C++11以后,STL里面的容器也对此做了调整
比如vector
的push_back
- 当实参是⼀个左值时,容器内部继续调用拷贝构造进行拷贝,将对象拷贝到容器空间中的对象
- 当实参是⼀个右值时,容器内部则调用移动构造,右值对象的资源到容器空间的对象上
四,类型分类
- C++11以后,进⼀步对类型进⾏了划分,右值被划分纯右值(pure value,简称prvalue)和将亡值
- 存右值和C++98中右值的概念相同
- 将忘值是指:返回右值引用的函数的调用表达式 或 转换为右值引用的转换函数的调用表达,如:
move(x)
、static_cast<X&&>(x)
【可以理解为:x
是左值,且一直是左值属性,但是move(x)
这一下,变成了将亡值,当右值】 static_cast<type>(x)
是类型转换操作,在这里:type
如果是左值引用,static_cast<type>(x)
该将亡值就是左值属性,反之就是右值属性。而x
是保留原来的属性- 范左值:左值和将亡值
五,引用折叠
C++中不能直接定义引用的引用如 int& && r = i
; ,这样写会直接报错,通过模板或 typedef
中的类型操作可以构成引用的引用
引用折叠:当出现引用的引用时,只要有左值引用,那类型就是左值引用
示例(typedef
):
typedef int& lref;typedef int&& rref;int n = 0;lref& r1 = n; // r1 的类型是 int&(左+左 = 左)lref&& r2 = n; // r2 的类型是 int& (左 + 右 = 左)rref& r3 = n; // r3 的类型是 int& (右 + 左 = 左)rref&& r4 = 1; // r4 的类型是 int&& (右 + 右 = 右)
示例(模板实例化):
函数f1
和f2
// 由于引用折叠,且T& 是左值引用,所以:f1实例化以后总是左值引用
template<class T>
void f1(T& x)
{}// 由于引用折叠限定,且T&& 是右值引用,则f2实例化后可以是左值引,也可以是右值引用
template<class T>
void f2(T&& x)
{
}
实例化分析:
// 没有折叠->实例化为void f1(int& x)f1<int>(n);f1<int>(0); // 报错// 折叠->实例化为void f1(int& x)f1<int&>(n);f1<int&>(0); // 报错// 折叠->实例化为void f1(int& x)f1<int&&>(n);f1<int&&>(0); // 报错// 折叠->实例化为void f1(const int& x)f1<const int&>(n);f1<const int&>(0);// 折叠->实例化为void f1(const int& x)f1<const int&&>(n);f1<const int&&>(0);// 没有折叠->实例化为void f2(int&& x)f2<int>(n); // 报错f2<int>(0);// 折叠->实例化为void f2(int& x)f2<int&>(n);f2<int&>(0); // 报错// 折叠->实例化为void f2(int&& x)f2<int&&>(n); // 报错f2<int&&>(0);
所以,当我们的模板写成右值引用的时候,这时候是万能引用模板。编译器可以根据我们传入的引用的类型不同,实例化成左值引用或者右值引用。(折叠的是:T& / T&&
,但对于T
本身而言,这种显式实例化:T
传入什么就是什么)
一个万能模板的例子:
template<class T>
void Function(T && t)
{int a = 0;T x = a;//x++;cout << &a << endl;cout << &x << endl << endl;
}
int main()
{// 10是右值,推导出T为int,模板实例化为void Function(int&& t)Function(10); // 右值int a = 10;// a是左值,推导出T为int&,引用折叠,模板实例化为void Function(int& t)Function(a); // 左值// std::move(a)是右值,推导出T为int,模板实例化为void Function(int&& t)Function(std::move(a)); // 右值const int b = 8;// a是左值,推导出T为const int&,引⽤折叠,模板实例化为void Function(const int&t)// 所以Function内部会编译报错,x不能++Function(b); // const 左值// std::move(b)右值,推导出T为const int,模板实例化为void Function(const int&&// 所以Function内部会编译报错,x不能++Function(std::move(b)); // const 右值return 0;
}
但是这里要注意的是:T
的类型由编译器推导。
因为T&&
是右值引用,当传左值的时候,为了匹配左值,T会被推导成左值引用
六,完美转发
完美转发:让参数保持原有的属性传递。
通常使用在解决这样的问题:一个为右值的参数,在传递时变成了左值。
例如:
template<class T>
void Function(T&& t)
{Fun(t);
}
Function(10)
假如,传入的实参10
是一个右值,形参t
就是一个右值引用。
但是右值引用本身的属性是左值,即:Function
里面的具名对象t
是一个左值,再传入Fun
的时候,传入的就是一个左值了。出现了属性的变化。
完美转发:
template<class T>
void Function(T&& t)
{Fun(forward<T>(t));
}
forward
的作用是根据模板参数 T
的推导结果,将参数以原始的左值或右值属性转发给其他函数。
forward
是一个函数模板,原型是(本质是通过:引用折叠 + 强制类型转换实现的):
template <class _Ty>
_Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept
{ // forward an lvalue as either an lvalue or an rvalue
return static_cast<_Ty&&>(_Arg);
}
即:
- 当
Function
传入10
:则T
被推导成int
,forward
返回的static_cast<int&&>(t)
属性是右值,所以是以右值的属性转发给Fun
- 传入一个左值
int x;
:则T
被推导成int&
,forward
返回的static_cast<int& &&>(t)
发生引用折叠,变成static_cast<int&>(t)
,属性是左值,以左值的属性转发给Fun
- 注意:
static_cast<_Ty&&>(_Arg)
这玩意是一个整体,这是一个将亡值。
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!
相关文章:
【C++11】右值引用和移动语义:万字总结
📝前言: 这篇文章我们来讲讲右值引用和移动语义 🎬个人简介:努力学习ing 📋个人专栏:C学习笔记 🎀CSDN主页 愚润求学 🌄其他专栏:C语言入门基础,python入门基…...
29、简要描述三层架构开发模式以及三层架构有哪些好处?
三层架构开发模式概述 三层架构(3-Tier Architecture)是一种将软件系统按功能模块垂直拆分为三个独立逻辑层的经典设计模式,自20世纪90年代提出以来,已成为企业级应用开发的主流范式。其核心思想是通过职责分离和松耦合设计&…...
PotPlayer,强大的高清视频播放器
PotPlayer 是一款强大的的高清视频播放器,兼容多种音频和视频格式,支持多种硬件加速解码,包括DXVA、CUDA、QuickSync等。支持立体视频播放技术、字幕支持、截屏工具以及视频录制等多种功能。文末获取! 1.鼠标右键【PotPlayer】压…...
AI数字人:未来职业的重塑(9/10)
摘要:AI 数字人凭借计算机视觉、自然语言处理与深度学习技术,从虚拟形象进化为智能交互个体,广泛渗透金融、教育、电商等多领域,重构职业生态。其通过降本提效、场景拓展与体验升级机制,替代重复岗位工作,催…...
Qt开发:如何加载样式文件
文章目录 一、加载图片资源二、QSS的使用介绍三、QSS的应用步骤与示例 一、加载图片资源 右键项目->选择"Add New…“之后,会弹出如下界面: 选择Qt->Qt Resource File即可。 点击下一步 点击上图中的LoadImageDemo.qrc文件,右…...
【10分钟读论文】Power Transmission Line Inspections电力视觉水文
标题Power Transmission Line Inspections: Methods, Challenges, Current Status and Usage of Unmanned Aerial Systems 2024 评分一颗星 论文《Power Transmission Line Inspections: Methods, Challenges, Current Status and Usage of Unmanned Aerial Systems》的核心内…...
[详细无套路]MDI Jade6.5安装包下载安装教程
目录 1. 软件包获取 2. 下载安装 3. 启动 4. 问题记录 写在前面: 垂死病中惊坐起,JAVA博主居然开始更博客了~ 最近忙项目了, 没啥更新的动力,见谅~见谅~. 这次博主的化工友友突然让帮安装JADE6.5软件,本来以为不就一个软件,直接拿捏. 不料竟然翻了个小车, 反被拿捏了. 既…...
Spring Boot 参考文档导航手册
📚 Spring Boot 参考文档导航手册 🗺️ ✨ 新手入门 👶 1️⃣ 📖 基础入门:概述文档 | 环境要求 | 安装指南 2️⃣ 🔧 实操教程:上篇 | 下篇 3️⃣ 🚀 示例运行:基础篇 …...
多个请求并行改造
改成 compose 页面的recompose次数 有时候recompose次数没必要优化,除非真的影响到性能了...
前端与Rust后端交互:跨越语言鸿沟 (入门系列三)
作为前端开发者,在Tauri应用中与Rust后端交互可能是最陌生的部分。本文将帮助你理解这一过程,无需深入学习Rust即可实现高效的前后端通信。 极简上手项目 apkParse-tauri 命令系统:前端调用Rust函数 Tauri的核心通信机制是"命令系统&q…...
ClickHouse查询执行与优化
SQL语法扩展与执行计划分析 特殊函数与子句 WITH子句:定义临时表达式(CTE),复用中间结果。 WITH tmp AS (SELECT ...) SELECT * FROM tmp ANY修饰符:在JOIN时仅保留第一个匹配的行(避免笛卡尔积爆炸&…...
[Kaggle]:使用Kaggle服务器训练YOLOv5模型 (白嫖服务器)
【核知坊】:释放青春想象,码动全新视野。 我们希望使用精简的信息传达知识的骨架,启发创造者开启创造之路!!! 内容摘要:最近需要使用 YOLOv5 框架训练一个识别模型…...
Debian安装避坑
Debian安装避坑 不要联网安装不支持root直接登陆默认没有ssh服务默认没有sudo命令 不要联网安装 安装系统的时候不要联网安装, 直接关闭网卡 否则在线下载最新的包非常耗时间. 不支持root直接登陆 ssh <创建的普通用户名>机器ip默认没有ssh服务 # 安装ssh服务 apt ins…...
Android Gradle插件开发
文章目录 1. Gradle插件是什么2. 为什么需要插件3. 编写插件位置4. 编写插件5. 自定义插件扩展5.1 订阅扩展对象5.2 把扩展添加给Plugin并使用5.3 配置参数5.4 嵌套扩展5.4.1 定义扩展5.4.2 获取扩展属性5.4.3 使用5.4.4 执行5.4.5 输出 6. 编写在单独项目里6.1 新建Module6.2 …...
goweb项目结构以及如何实现前后端交互
项目结构 HTML模板 使用ParseFiles可以解析多个模板文件 func ParseFiles(filenames ...string)(*Teplate,error){return parseFiles(nil,filenames...) }把模板信息响应写入到输入流中 func (t *Template) Exwcute(wr io.Writer,data interface{})error{if err:t.escape();…...
Astro canvas大屏从iotDA上抽取设备影子的参数的详细操作实施路径
目录 🛠 场景: 🎯 核心思路 🗺 详细操作实施路径(针对小白版) 🚛 第1步:配置桥接器(建立连接通道) 📋 第2步:配置数据集…...
Ardunio学习
程序书写 Ardunio程序安装 在 Arduino的官方网站上可以下载这款官方设计的软件及源码、教程和文档。Arduino IDE的官方下载地址 为:http://arduino.cc/en/Main/Software。登录官网,下载软件并安装。 https://www.arduino.cc/。 安装成功后࿰…...
dl学习笔记(13):从强化学习到PPO
一、我们为什么要有强化学习 为了更好的有一个宏观感受,下图是DeepMind在2024发表的文章中对AI做出了不同层次的定义 可以看到左边分为了5个不同层次的AI,中间是对于细分的下游任务AI的能力展现,右边则是通用任务的AGI实现。我们可以看到中间…...
【运维】云端掌控:用Python和Boto3实现AWS资源自动化管理
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在云计算时代,AWS(Amazon Web Services)作为领先的云服务平台,其资源管理的高效性对企业至关重要。本文深入探讨如何利用Python的boto3…...
数字技术驱动下教育生态重构:从信息化整合到数字化转型的路径探究
一、引言 (一)研究背景与问题提出 在当今时代,数字技术正以前所未有的速度和深度渗透到社会的各个领域,教育领域也不例外。从早期的教育信息化整合到如今的数字化转型,教育系统正经历着一场深刻的范式变革。 回顾教…...
《数据库系统工程师》-B站-视频截图整理-2021-23
在2024年准备软考《数据库系统工程师》,跟着B站UP主学习的视频截图记录,当然考试也顺利通过了(上午下午都是50多分)。 在视频评论区还愿下面看到有人问我的截图资源。 我当时学习用的钉钉的teambition做的记录,在线文档…...
【PINN】DeepXDE学习训练营(5)——function-mf_dataset.py
一、引言 随着人工智能技术的飞速发展,深度学习在图像识别、自然语言处理等领域的应用屡见不鲜,但在科学计算、工程模拟以及物理建模方面,传统的数值方法仍然占据主导地位。偏微分方程(Partial Differential Equations, PDEs&…...
lnmp1.5+centos7版本安装php8
1、问题: 1nmp1.5不支持php8 解决办法: 下载lnmp2.1,进入到2.1版本执行安装php多版本命令,选择php8 2、编译安装php8时报C错误问题 解决办法: 安装php8.0报错A compiler with support for C17 language features is required…...
Netmiko 源码解析
1. 源码结构概览 Netmiko 的代码库主要分为以下核心模块: netmiko/ ├── base_connection.py # 连接基类(核心逻辑) ├── cisco/ # Cisco 设备实现类 ├── juniper/ # Juniper 设备实现类 ├── hp_…...
WPF大数据展示与分析性能优化方向及代码示例
WPF大数据展示与分析性能优化指南 一、大数据展示性能优化方向 1. 虚拟化技术 核心思想:只渲染可见区域的数据,动态加载/卸载数据项 实现方式: 使用VirtualizingStackPanel(WPF内置)自定义虚拟化容器(如VirtualizingWrapPanel)代码示例: &…...
Redis的ZSet对象底层原理——跳表
我们来聊聊「跳表(Skip List)」,这是一个既经典又优雅的数据结构,尤其在 Redis 中非常重要,比如 ZSet(有序集合)底层就用到了跳表。 🌟 跳表(Skip List)简介 …...
SpringCloud组件——OpenFeign
一.使用 1.为什么要使用 OpenFeign是⼀个声明式的WebService客户端。它让微服务之间的调用变得更简单,类似controller调用service, 只需要创建⼀个接口,然后添加注解即可使用OpenFeign。 2.引入依赖 加下面的依赖引入到服务消费者中&…...
C#里使用libxl来创建EXCEL文件然后发送到网络
前面一个例子说明了从网络直接读取EXCEL数据的方法, 本例子就说明怎么样创建一个EXCEL文件,也可以直接发送到网络,而不需要保存到文件,直接在内存里高效操作。 在这里要使用函数SaveRaw,输入参数是保存数据缓冲区和缓冲区的大小,返回数据和大小。 例子如下: private…...
物联网安全运营概览
这是第二篇博客文章,概述了实施物联网安全及其运行之前所需的内容。上次,我们概述了物联网安全。为了让您更具体地了解它是什么,我们将首先解释它是如何工作的,然后介绍设备 ID、部署选项和许可的概念。 物联网安全各个组件之间的关系如下图所示:基于此图,我们先来看一下…...
如何给GitHub项目提PR(踩坑记录
Fork 项目 (Fork the Repository): 在你使用的代码托管平台(如 GitHub、GitLab)上,找到你想要贡献的原始项目仓库。点击 "Fork" 按钮。这会在你自己的账户下创建一个该项目的完整副本(你的 Fork 仓库)。 克…...
Redux和MobX有什么区别
Redux 和 MobX 都是用于 React 应用的全局状态管理库,但它们在设计理念、使用方式和适用场景等方面存在明显的区别,下面为你详细分析: 1. 设计理念 Redux:基于 Flux 架构,遵循单向数据流和纯函数式编程的理念。状态是…...
测试模板x
本篇技术博文摘要 🌟 引言 📘 在这个变幻莫测、快速发展的技术时代,与时俱进是每个IT工程师的必修课。我是盛透侧视攻城狮,一名什么都会一丢丢的网络安全工程师,也是众多技术社区的活跃成员以及多家大厂官方认可人员&a…...
dubbo 隐式传递
隐式传递 隐式传递的应用 传递请求流水号,分布式应用中通过链路追踪号来全局检索日志传递用户信息,以便不同系统在处理业务逻辑时可以获取用户层面的一些信息传递凭证信息,以便不同系统可以有选择性地取出一些数据做业务逻辑,比…...
深入解析 ASP.NET Core 中的 ResourceFilter
在现代 Web 开发中,ASP.NET Core 提供了强大的过滤器(Filters)机制,用于在处理请求的不同阶段执行特定的代码逻辑。ASP.NET Core 中的 ResourceFilter 是一种非常有用的过滤器类型,允许开发人员在请求到达控制器操作方…...
Java进阶--面向对象设计原则
设计模式 概念 设计模式,又称软件设计模式,是一套被反复使用,经过分类编目的,代码设计经验的总结。描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方。它是解决特定问题的一系列套路,是…...
java每日精进 4.26【多租户之过滤器及请求处理流程】
一月没更,立誓以后断更三天我就是狗!!!!!!!! 研究多租户框架中一条请求的处理全流程 RestController RequestMapping("/users") public class UserControlle…...
【学习笔记】Stata
一、Stata简介 Stata 是一种用于数据分析、数据管理和图形生成的统计软件包,广泛应用于经济学、社会学、政治科学等社会科学领域。 二、Stata基础语法 2.1 数据管理 Stata 支持多种数据格式的导入,包括 Excel、CSV、文本文件等。 从 Excel 文件导入…...
[MySQL数据库] 事务与锁
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
Rule.issuer(通过父路径配置loader处理器)
说明 正常在设置loader配置规则时,都是通过文件后缀来配置的 issuer的作用是可以通过父级的路径,设置生效的匹配规则 与rule的差别 test: 匹配当前模块的路径(如 .css 文件) issuer: 匹配引入当前模块的父模块的路径࿰…...
MyBatis 插件开发的完整详细例子
MyBatis 插件开发的完整详细例子 MyBatis 插件(Interceptor)允许开发者在已映射语句执行过程中的某一点进行拦截调用,从而实现自定义逻辑。以下是一个完整的 MyBatis 插件开发示例,涵盖所有使用场景,并附有详细注释和总…...
树状数组底层逻辑探讨 / 模版代码-P3374-P3368
目录 功能 实现 Q:但是,c[x]左端点怎么确定呢? Q:那么为什么要以二进制为基础呢? Q:为什么是补码 - ? 区间查询 树形态 性质1.对于x<y,要么c[x]和c[y]不交,要么c[x]包含于c[y] 性质2.c[x] 真包含 于c[x l…...
Eigen库入门
Eigen是一个C模板库,用于线性代数运算,包括矩阵、向量、数值求解和相关算法。它以其高性能、易用性和丰富的功能而闻名。 安装与配置 Eigen是一个纯头文件库,无需编译,只需包含头文件即可使用。 下载Eigen:从官方网站…...
力扣HOT100——102.二叉树层序遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] /*** Definition for a bi…...
客户案例 | 光热+数智双驱动!恒基能脉的数字化协同与技术创新实践
光热先锋 智领未来 恒基能脉新能源科技有限公司: 创新驱动,智造光热未来行业领航者 恒基能脉新能源科技有限公司是一家立足于光热发电核心技术产品,专注于“光热” 多能互补项目的国家高新技术企业,其核心产品定日镜广泛应用于光热发电、储…...
第十六周蓝桥杯2025网络安全赛道
因为只会web,其他方向都没碰过,所以只出了4道 做出来的: ezEvtx 找到一个被移动的文件,疑似被入侵 提交flag{confidential.docx}成功解出 flag{confidential.docx} Flowzip 过滤器搜索flag找到flag flag{c6db63e6-6459-4e75-…...
构造函数有哪些种类?
构造函数用于对象的初始化。 1.默认构造函数:没有参数,执行默认的初始化操作; 2.参数化构造函数:传入参数的构造函数,允许构造函数初始化成员变量; 3.拷贝构造函数:将同一类型的实例化对象作…...
第十六届蓝桥杯大赛软件赛省赛 C/C++ 大学B组 [京津冀]
由于官方没有公布题目的数据, 所以代码仅供参考 1. 密密摆放 题目链接:P12337 [蓝桥杯 2025 省 AB/Python B 第二场] 密密摆放 - 洛谷 题目描述 小蓝有一个大箱子,内部的长宽高分别是 200、250、240(单位:毫米)&…...
关于调度策略的系统性解析与物流机器人应用实践
关于调度策略的系统性解析与物流机器人应用实践 一、调度策略的定义与核心目标 调度策略是用于在复杂环境中协调资源分配、任务排序及路径规划的决策框架,旨在通过优化资源利用率和任务执行效率,实现系统整体性能的最优解。其核心目标包括: 动态适应性:应对实时变化(如订…...
探索具身智能协作机器人:技术、应用与未来
具身智能协作机器人:概念与特点 具身智能协作机器人,简单来说,就是将人工智能技术与机器人实体相结合,使其能够在与人类共享的空间中进行安全、高效协作的智能设备。它打破了传统机器人只能在预设环境中执行固定任务的局限&#…...
毕业项目-Web入侵检测系统
1. 项目简介 系统主要分为两大板块:靶标站点和入侵检测系统。靶标站点是系统的被监测对象,而入侵检测系统则是用于检测靶标站点的流量是否存在异常,以及在检测到异常时进行告警。 入侵检测系统的实现过程简述如下: 数据获取与分…...