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

【C++】右值引用与完美转发

目录

一、右值引用:

1、左值与右值:

2、左值引用和右值引用:

二、右值引用的使用场景:

1、左值引用的使用场景:

2、右值引用的使用场景:

移动构造

移动赋值

三、完美转发:

1、万能引用:

2、实际使用:


一、右值引用:

1、左值与右值:

在了解右值引用前,要先了解什么是左值引用(其实在之前已经使用过很多回了),那么要了解什么是左值引用,就先要了解什么是左值什么是右值

在等号左边的值叫左值吗?在等号右边的值叫右值吗? 

显然定义不会这么简单的,但是左值可以出现赋值符号的左边,右值不能出现在赋值符号左边,也就是说在等号左边的值一定不是右值,在等号右边的可以是左值或右值

左值:

能够进行取地址的操作,也可以被修改

如下的a,b,c都是左值

int main()
{int a = 10;const int b = 10;int* c = new int(0);return 0;
}

右值:

不能够进行取地址的操作,一般不能够被修改

如下,10,x,fmin(x,y)的返回值就是右值

int main()
{double x = 1.1, y = 2.2;//如下就是右值10;x + y;fmin(x, y);return 0;
}

理解:

1、右值的本质是一个临时变量或者常量值
2、这些临时变量是没有被实际存储起来的,所以无法对右值取地址        
3、像上述的fmin的返回值,其实际上就是一份临时拷贝,所以算作右值

2、左值引用和右值引用:

什么是左值引用:

左值引用就是给左值取别名

int main()
{int a = 10;const int b = 10;int* c = new int(0);//这就是左值引用int& pa = a;const int& pb = b;int*& pc = c;return 0;
}

什么是右值引用:

右值引用就是给右值取别名

int main()
{double x = 1.1, y = 2.2;//如下就是右值10;x + y;fmin(x, y);//这个就是右值引用int&& p1 = 10;int&& p2 = x + y;int&& p3 = fmin(x, y);return 0;
}

这里在给右值取别名后,右值会被存储到特定的位置,此时就能够取到该位置的地址了

左值引用可以引用右值吗 ----- 可以

但是,左值引用不能直接引用右值,因为右值不能够被修改,左值可以修改,如果直接引用的话权限会存在放大问题,所以如果想要左值引用右值就需要加上const修饰

像我们之前在函数参数传参的时候经常写const T& x,这就是保证既能够传左值,又能够传右值

template<class T>
void func(const T& val)
{cout << val << endl;
}
int main()
{string s("111");func(s);       //s为左值func("222"); //"222"为右值return 0;
}

右值引用可以引用左值吗 ----- 可以

但是,右值引用也不能直接引用左值,如果想要引用左值,就需要加上move后的左值

int main()
{int a = 10;//右值引用给左值取别名int&& pa = move(a);return 0;
}

为什么加上move后才能让右值引用来引用左值呢?

我们首先要知道,左值引用或者右引用都是在给资源取别名,对于左值引用,就是直接指向原本的数据,对于右值引用,我们知道原本是没有空间资源的,那么右值引用引用右值就是首先开辟一块空间,然后将常量或者临时变量转移到开辟好的地方,然后在指向该地方

所以右值引用的本质是对右值进行资源的转移

此时就有空间资源了,此时就能够取地址了,并且能够对其进行修改了

对于常量,临时变量,表达式的结果这些右值,编译器在右值引用的时候会直接将这些右值进行转移资源,但是对于左值,编译器不敢直接转移,这个时候编译器就为用户提供了一个函数move,当进行move左值的时候,就能够让右值引用 引用左值了

二、右值引用的使用场景:

1、左值引用的使用场景:

左值引用既能够引用左值,又能够引用右值,但是还是存在短板,所以在C++11里面,引入了右值引用来弥补左值引用的短板

在左值引用中:

1、左值引用做参数,防止传参是的拷贝
2、左值引用做返回值,防止返回时对返回对象进行拷贝

首先,写一个自己的string类,在里面写上部分cout来方便打印观察

namespace ppr
{class string{public:typedef char* iterator;iterator begin(){return _str;//返回字符串中第一个字符的地址}iterator end(){return _str + _size;//返回字符串中最后一个字符的后一个字符的地址}//构造函数string(const char* str = ""){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}//交换两个对象的数据void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//拷贝构造函数(现代写法)string(const string& s):_str(nullptr),_size(0),_capacity(0){cout << "string(const string& s) -- 深拷贝" << endl;string tmp;swap(tmp);}//移动构造函数(现代写法)string(string&& s):_str(nullptr), _size(0), _capacity(0){cout << "string(string&& s) -- 移动构造" << endl;swap(s);}//赋值运算符重载(现代写法)string& operator=(const string& s){cout << "string& operator=(const string& s) -- 深拷贝" << endl;string tmp;swap(tmp);return *this;}//析构函数~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}//[]运算符重载char& operator[](size_t i){assert(i < _size);return _str[i];}//改变容量,大小不变void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strncpy(tmp, _str, _size + 1);delete[] _str;_str = tmp;_capacity = n;}}//尾插字符void push_back(char ch){if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_str[_size + 1] = '\0';_size++;}//+=运算符重载string operator+=(char ch){push_back(ch);string tmp(*this);return tmp;}//返回C类型的字符串const char* c_str()const{return _str;}private:char* _str;size_t _size;size_t _capacity;};
}

接着看看左值引用的使用场景

//首先,看看左值引用的使用场景
//值传参
void func1(ppr::string s)
{cout << "void func1(ppr::string s)" << endl;
}
//左值引用传参
void func2(const ppr::string& s)
{cout << "void func2(const ppr::string& s)" << endl;
}int main()
{ppr::string ret1("1111111111111");func1(ret1);//这里采用深拷贝func2(ret1);ret1 += '0';//里面return *this 的时候,也会进行拷贝构造return 0;
}

其中,在func1的时候,传值传参会进行一次拷贝构造,在+=那里,返回* this的时候,也会进行一次拷贝构造这样的话会看到两次深拷贝

左值引用短板:

左值引用能够避免不必要的拷贝构造,但是并不能完全避免

左值引用做参数的时候,能够完全避免传参时的拷贝
左值引用做返回值的时候,不能完全避免拷贝

比如如果返回的是一个局部变量,在返回的时候局部变量被销毁了,此时如果使用左值引用进行返回,就会返回的野指针,此时就不能够用左值引用返回,需要老老实实地值拷贝

如下会进行两次拷贝操作,然后将ret返回

如果在新一点的编译器会进行优化,只需进行一次拷贝操作

如果是引用传参,此时局部变量的局部空间,在出了函数作用域之后就会被释放,此时就会出问题

所以,C++11为了解决这类问题,提出了右值引用来解决这种场景

2、右值引用的使用场景:

右值分为 纯右值将亡值

纯右值:内置类型的右值
将亡值:自定义类型的右值

右值引用和移动语句解决上述问题的方式就是,给当前模拟实现的string类增加移动构造方法

移动构造

移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己

如果没加上述的移动拷贝,就会出现深拷贝

如果加上移动构造,那么就会走移动构造函数,这样就能更加减少拷贝

移动构造的本质就是将参数的右值窃取过来,占为己有,这样它就不用再深度拷贝了,所以叫做移动构造

移动构造和拷贝构造的区别:

1、在没有增加移动构造之前,由于拷贝构造采用的是const左值引用接收参数,因此无论拷贝构造对象时传入的是左值还是右值,都会调用拷贝构造函数
2、增加移动构造之后,由于移动构造采用的是右值引用接收参数,因此如果拷贝构造对象时传入的是右值,那么就会调用移动构造函数
3、string的拷贝构造函数做的是深拷贝,而移动构造函数中只需要调用swap函数进行资源的转移,因此调用移动构造的代价比调用拷贝构造的代价小

左值引用:直接引用对象以减少拷贝

右值引用:间接减少拷贝,将临时资源等将亡值的资源通过 移动构造 进行转移,减少拷贝

移动赋值

移动赋值是一个赋值运算符重载函数,该函数的参数是右值引用类型的,移动赋值也是将传入右值的资源窃取过来,占为己有,这样就避免了深拷贝,之所以它叫移动赋值,就是窃取别人的资源来赋值给自己的意思

// 赋值重载
string& operator=(const string& s) 
{cout << "string& operator=(string s) -- 深拷贝" << endl; string tmp(s); swap(tmp); return *this;
}
//移动赋值
string& operator=(string&& s) 
{cout << "string& operator=(string && s) -- 移动拷贝" << endl; swap(s); return *this;
}

string& operator=(const string& s) 和string& operator=(string&& s) 的区别:

1、在没有string& operator=(string&& s) 的时候,如果进行=操作,那么无论是左值还是右值传参都会调用string& operator=(const string& s) 这个函数

2、在增加移动赋值后,如果是左值就调用原来的函数,如果是右值就调用新加的移动赋值函数

3、移动赋值函数是通过swap函数进行资源的交换,而原来的operator=是通过深拷贝进行,因此,移动赋值的代价比原来的要小

三、完美转发:

1、万能引用:

template<class T>
void PerfectForward(T&& t)
{//...
}

这里函数中的参数并不是右值引用,如果传的模板是左值,这里的参数就是左值引用,相反如果传的模板是右值,那么这里的参数就是右值引用

void func(int& a)
{cout << "左值引用" << endl;
}
void func(const int& a)
{cout << "const 左值引用" << endl;
}
void func(int&& a)
{cout << "右值引用" << endl;
}
void func(const int&& a)
{cout << "const 右值引用" << endl;
}
template<class T>
void perfectForward(T&& val)
{func(val);
}int main()
{int a = 10;perfectForward(a); //左值const int b = 10;  //const 左值perfectForward(b);perfectForward(move(a)); // 右值perfectForward(move(b)); //const 右值return 0;
}

如上,这就是通过func函数重载,来观察编译器会怎样进行函数调用

如上,这是运行结果,为什么会这样呢?难道是编译器做的不对吗,在实际调用中,4个函数没有一个是进入了右值引用,均匹配的是左值引用版本,这是为什么呢?

当对右值进行引用后,会导致右值被存储到特定的位置,此时就能够对这个引用后的右值进行取地址了,这样的话,这个右值就模版被识别成左值了

也就是说,在右值引用过一次后,会导致右值变成左值,但是如果想要继续保证其右值的属性,此时就需要用到完美转发

如上,在对右值引用进行传参的时候,在前面加上forward<T>,这样经过完美转发后,调用PerfectForward函数时传入的是右值就会匹配到右值引用版本的Func函数,传入的是const右值就会匹配到const右值引用版本的Func函数

forward是一个模板函数,需要指定模板参数类型T,确保能正确推导并传递

2、实际使用:

首先实现一个建议的list,在其中实现左值引用的push_back和insert函数

namespace ppr
{template<class T>struct ListNode{T _data;ListNode* _next = nullptr;ListNode* _prev = nullptr;};template<class T>class list{typedef ListNode<T> node;public://构造函数list(){_head = new node;_head->_next = _head;_head->_prev = _head;}//左值引用版本的push_backvoid push_back(const T& x){insert(_head, x);}//右值引用版本的push_backvoid push_back(T&& x){insert(_head, x);}//左值引用版本的insertvoid insert(node* pos, const T& x){node* prev = pos->_prev;node* newnode = new node;newnode->_data = x;prev->_next = newnode;newnode->_prev = prev;newnode->_next = pos;pos->_prev = newnode;}//右值引用版本的insertvoid insert(node* pos, T&& x){node* prev = pos->_prev;node* newnode = new node;newnode->_data = x;prev->_next = newnode;newnode->_prev = prev;newnode->_next = pos;pos->_prev = newnode;}private:node* _head; //指向链表头结点的指针};
}

接着进行左值和右值的push_back版本的调用

int main()
{ppr::list<ppr::string> lt;ppr::string s1("111111111111111");//左值的push_backlt.push_back(s1);cout << endl << endl;ppr::string s2("111111111111111");//右值的push_backlt.push_back(move(s2));cout << endl << endl;lt.push_back("22222222222222222");//右值的push_backreturn 0;
}

但是会发现全部都是深拷贝,这和上述右值被引用后,就可以取地址了,就变成左值了,所以为了避免这种情况,就需要在右值版本的push_back和insert加上完美转发,让右值能够保存右值属性

相关文章:

【C++】右值引用与完美转发

目录 一、右值引用&#xff1a; 1、左值与右值&#xff1a; 2、左值引用和右值引用&#xff1a; 二、右值引用的使用场景&#xff1a; 1、左值引用的使用场景&#xff1a; 2、右值引用的使用场景&#xff1a; 移动构造 移动赋值 三、完美转发&#xff1a; 1、万能引用…...

批量合并 PDF 文档,支持合并成单个文档,也支持按文件夹合并 PDF 文档

在日常工作中&#xff0c;合并多个 PDF 文档为一个文件是非常常见的需求。通过合并 PDF&#xff0c;不仅能够更方便地进行管理&#xff0c;还能在特定场景下&#xff08;如批量打印&#xff09;提高效率。那么&#xff0c;当我们需要批量合并多个 PDF 文件时&#xff0c;是否有…...

SQL Server 备份相关信息查看

目录标题 一、统计每个数据库在不同备份目录和备份类型下的备份次数&#xff0c;以及最后一次备份的时间整体功能详细解释 二、查询所有完整数据库备份的信息&#xff0c;包括备份集 ID、数据库名称、备份开始时间和备份文件的物理设备名称&#xff0c;并按备份开始时间降序排列…...

Flutter_学习记录_AppBar中取消leading的占位展示

将leading设置为null将automaticallyImplyLeading设置为false 看看automaticallyImplyLeading的说明&#xff1a; Controls whether we should try to imply the leading widget if null. If true and [AppBar.leading] is null, automatically try to deduce what the leading…...

多省发布!第27届中国机器人及人工智能大赛各赛区比赛通知

01 大赛介绍 中国机器人及人工智能大赛是由中国人工智能学会主办的极具影响力的全国性学科竞赛&#xff0c;旨在推动我国机器人及人工智能技术的创新与应用&#xff0c;促进相关专业的人才培养。作为全国高校学科竞赛A类赛事&#xff0c;该比赛吸引了众多高校和科研机构的积极…...

leetcode199 二叉树的右视图

小问题&#xff1a;if(!q.empty()) 这个条件会导致只处理一层&#xff0c;而不会处理所有层。正确的做法应该是用 while(!q.empty()) 循环处理每一层。 class Solution { public:vector<int> rightSideView(TreeNode* root) {vector<int> res;queue<TreeNode…...

大模型评测框架evalscope、openCompass

一、evalscope使用说明 1、如何使用智增增的接口&#xff1a; VLLM_USE_MODELSCOPETrue evalscope eval \--model qwen2.5-14b-instruct \--api-url https://api.zhizengzeng.com/v1/chat/completions \--api-key skxxx \--eval-type service \--datasets gsm8k \--limit 10 …...

接口自动化——初识pytest

缩写单词含义.passed通过Ffailed失败&#xff08;用例执行时报错&#xff09;Eerror出错&#xff08;fixture执行报错&#xff09;sskipped跳过Xxpassed预期外的通过&#xff08;不符合预期&#xff09;xxfailed预期内的失败&#xff08;符合预期&#xff09; 1.pytest 配置 1…...

SkyWalking实战

1、下载SkyWalking APM 1.手动下载 Downloads | Apache SkyWalkinghttps://skywalking.apache.org/downloads/ 2.链接下载 https://dlcdn.apache.org/skywalking/10.2.0/apache-skywalking-apm-10.2.0.tar.gzhttps://dlcdn.apache.org/skywalking/10.2.0/apache-skywalking-…...

游戏AI实现-GOAP

GOAP原理&#xff1a; GOAP&#xff08;面向目标的行动规划&#xff0c;Goal - Oriented Action Planning&#xff09; 旨在让智能体通过选择一系列行动来达成特定目标。它基于对世界状态的理解&#xff0c;每个行动都有前提条件和效果。智能体通过分析当前世界状态与目标状态…...

Baklib内容中台的核心优势是什么?

智能化知识管理引擎 Baklib的智能化知识管理引擎通过多源数据整合与智能分类技术&#xff0c;实现企业知识资产的自动化归集与动态更新。系统内置的语义分析算法可自动识别文档主题&#xff0c;结合自然语言处理技术生成结构化标签体系&#xff0c;大幅降低人工标注成本。针对…...

windows第二十章 单文档应用程序

文章目录 单文档定义新建一个单文档应用程序单文档应用程序组成&#xff1a;APP应用程序类框架类&#xff08;窗口类&#xff09;视图类&#xff08;窗口类&#xff0c;属于框架的子窗口&#xff09;文档类&#xff08;对数据进行保存读取操作&#xff09; 直接用向导创建单文档…...

eBay多账号安全运营技术体系:从环境隔离到智能风控的工程化实践

一、多账号运营风险模型解析 &#xff08;技术化重构关联检测机制&#xff09; 环境指纹维度&#xff1a; 浏览器指纹参数&#xff1a;Canvas/WebGL渲染特征&#xff08;差异度要求≥98%&#xff09; 设备指纹参数&#xff1a;GPU型号/声卡特征&#xff08;识别准确率92%&…...

《Python Web网站部署应知应会》No4:基于Flask的调用AI大模型的高性能博客网站的设计思路和实战(上)

基于Flask的调用AI大模型的高性能博客网站的设计思路和实战&#xff08;上&#xff09; 摘要 本文详细探讨了一个基于Flask框架的高性能博客系统的设计与实现&#xff0c;该系统集成了本地AI大模型生成内容的功能。我们重点关注如何在高并发、高负载状态下保持系统的高性能和…...

vulnhub-Node1

一、信息收集 1、扫靶机ip arp-scan -l 2、端口扫描 淦&#xff0c;只有22端口和3000端口&#xff0c;访问一下3000端口吧&#xff0c;估计是个网页 nmap -p- -Pn -sC -sV -n 192.168.66.130PORT STATE SERVICE VERSION 22/tcp open ssh OpenSS…...

什么是 OLAP 数据库?企业如何选择适合自己的分析工具

引言&#xff1a;为什么企业需要 OLAP 数据库&#xff1f; 你是否曾经经历过这样的场景&#xff1a; 市场部门急需一份用户行为分析报告&#xff0c;数据团队告诉你&#xff1a;“数据太大了&#xff0c;报表要跑 4 个小时”&#xff1b;业务负责人在会议中提出一个临时性分析…...

计算机视觉准备八股中

一边记录一边看&#xff0c;这段实习跑路之前运行完3DGAN&#xff0c;弄完润了&#xff0c;现在开始记忆八股 1.CLIP模型的主要创新点&#xff1a; 图像和文本两种不同模态数据之间的深度融合、对比学习、自监督学习 2.等效步长是每一步操作步长的乘积 3.卷积层计算输入输出…...

电源系统的热设计与热管理--以反激式充电器为例

前言 反激电源常用于各种电子设备中&#xff0c;比如充电器、适配器等&#xff0c;它们通过变压器进行能量转换。高温环境可能对电子元件造成影响&#xff0c;特别是像MOSFET、二极管、变压器这样的关键部件&#xff0c;导致效率变低&#xff0c;甚至可能导致功能失效。还有安…...

【云服务器】在Linux CentOS 7上快速搭建我的世界 Minecraft 服务器搭建,并实现远程联机,详细教程

【云服务器】在Linux CentOS 7上快速搭建我的世界 Minecraft 服务器搭建&#xff0c;详细详细教程 一、 服务器介绍二、下载 Minecraft 服务端三、安装 JDK 21四、搭建服务器五、本地测试连接六、添加服务&#xff0c;并设置开机自启动 前言&#xff1a; 推荐使用云服务器部署&…...

vue数据两个相同的参数对比只显示一个

vue数据两个相同的参数对比只显示第一个 如每条的rq0/rq1对比data() { return{dataList: [{CurrencyName: "现金",rq0: "2017-10-20 19:22:17",rq1: "2018-02-07 19:48:00",yje: -1179.8},{CurrencyName: "微支付",rq0: "2017-10…...

vue如何实现前端控制动态路由

在 Vue.js 中&#xff0c;动态路由是一种根据不同用户权限或其他因素动态改变路由列表的功能。这种机制允许开发者根据后端提供的权限数据动态渲染前端路由&#xff0c;实现多用户权限系统&#xff0c;不同用户展示不同的导航菜单。 动态路由的配置 动态路由的配置涉及到前端…...

开发环境部署

一、安装Django-5.0.3 1、将已下载的软件通过winscp上传至centos下 2、 安装 [root@hcss-ecs-1e19 ~]# ll total 10372 -rw-r--r-- 1 root root 10620661 Feb 10 10:16 Django-5.0.3.tar.gz [root@hcss-ecs-1e19 ~]# pip3 install Django-5.0.3.tar.gz Processing ./Django-…...

C语言入门教程100讲(0)从了解C语言的发展史开始

文章目录 引言1. C语言的起源2. C语言的诞生3. C语言的标准化4. C语言的进一步发展5. C语言的影响与应用6. C语言的未来结语引言 C语言作为一种高效、灵活且具有广泛应用的编程语言,在计算机科学史上占据着举足轻重的地位。它的设计不仅影响了后来的编程语言,也对操作系统、…...

笔记本电脑更换主板后出现2203:System configuration is invalid,以及2201、2202系统错误的解决

笔记本电脑更换主板后启动出现2203:System configuration is invalid,以及2201、2202系统错误的解决 自用的一台ThinkpadT490笔记本电脑 ,由于主板故障,不得不更换主板,通过某宝购置主板后进行了更换。 具体拆卸笔记本可搜索网络视频教程。 注意: 在更换主板时,注意先拍…...

如何为 Debian 和 Kali 系统更换软件源并更新系统

在 Linux 系统中&#xff0c;软件源&#xff08;Software Repository&#xff09;是获取软件包和更新的核心途径。然而&#xff0c;默认的软件源可能会因为地理位置、网络状况等原因导致下载速度缓慢&#xff0c;甚至无法访问。为了提升系统的软件获取效率&#xff0c;许多用户…...

git:远程仓库拉取到本地,fork到本地,修改后再上传

讲述仓库成员拉取远程仓库&#xff08;即组长的仓库&#xff0c;里面有成员&#xff09;到本地&#xff0c;修改内容再上传的详细步骤&#xff1a; 1.进入仓库&#xff0c;首先fork &#xff08;如不&#xff0c;所作操作会直接对远程仓库进行&#xff0c;不用管理员审核&…...

C++ 中名字的作用域、概念、嵌套与实践(十八)

1. 名字的作用域基本概念 作用域&#xff08;scope&#xff09; 指的是程序中的一个区域&#xff08;通常被花括号 {} 包围&#xff09;&#xff0c;在这里一个名字&#xff08;如变量名、函数名、类名等&#xff09;有其特定含义。 在 同一个作用域 中&#xff0c;一个名字只…...

Go语言nil原理深度解析:底层实现与比较规则

Go语言nil原理深度解析&#xff1a;底层实现与比较规则 引言 在Go语言中&#xff0c;nil 是一个特殊的关键字&#xff0c;用于表示引用类型的“零值”。它在指针、切片、映射、通道、接口和函数等类型中广泛使用。本文将从 底层实现、比较规则、与其他语言的对比 等角度&#…...

使用Java操作Redis

文章目录 常用Redis键操作命令使用Java操作Redis配置 Redis 连接信息创建 Maven 项目结构 操作字符串操作列表操作集合操作散列操作有序集合总结 报错解决办法&#xff1a; 当使用redis-cli连接客户端出现not connected时 使用redis-cli -h 192.168.222.101 -p 6379即可解决 …...

开源的CMS建站系统可以随便用吗?有什么需要注意的?

开源CMS建站系统虽然具有许多优点&#xff0c;但并非完全“随便用”。无论选哪个CMS系统&#xff0c;大家在使用的时候&#xff0c;可以尽可能地多注意以下几点&#xff1a; 1、版权问题 了解开源许可证&#xff1a;不同的开源CMS系统采用不同的开源许可证&#xff0c;如GPL、…...

数据结构:探秘AVL树

本节重点 理解AVL树的概念掌握AVL树正确的插入方法利用_parent指针正确更新平衡因子掌握并理解四种旋转方式&#xff1a;左单旋&#xff0c;右单旋&#xff0c;左右双旋&#xff0c;右左双旋 一、AVL树的概念 AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis&…...

C++ 变量与初始化详解(十五)

1. 变量定义 在 C 中&#xff0c;定义变量的基本形式通常是先写出 类型说明符&#xff08;type specifier&#xff09;&#xff0c;后面紧跟由逗号分隔的一个或多个变量名&#xff0c;最后以分号结束。简单示例如下&#xff1a; int sum 0, value, units_sold 0; Sales_ite…...

【网络协议详解】—— STP 、RSTP、MSTP技术(学习笔记)

一、STP技术工作原理 STP&#xff08;Spanning Tree Protocol&#xff09;生成树协议&#xff08;IEEE 802.1D&#xff09;是一种网络协议&#xff0c;用于在网络拓扑中防止环路的产生。在二层交换网络中&#xff0c;逻辑上阻塞部分接口&#xff0c;实现从根交换机到所有节点的…...

C++中将记录集的数据复制到Excel工作表中的CRange类CopyFromRecordset函数异常怎么捕获

文章目录 一、异常类型及捕获逻辑二、完整代码示例三、关键错误场景与解决方案1. CopyFromRecordset 返回空数据2. COM错误 0x800A03EC3. Excel进程残留4. 内存不足 四、调试与日志记录1. 启用详细日志2. 捕获错误描述3. 调试断点 五、最佳实践 在C中使用 CRange::CopyFromReco…...

综述速读|086.04.24.Retrieval-Augmented Generation for AI-Generated Content A Survey

论文题目&#xff1a;Retrieval-Augmented Generation for AI-Generated Content: A Survey 论文地址&#xff1a;https://arxiv.org/abs/2402.19473 bib引用&#xff1a; misc{zhao2024retrievalaugmentedgenerationaigeneratedcontent,title{Retrieval-Augmented Generation…...

对内核fork进程中写时复制的理解记录

前言 文章写于学习Redis时对aof后台重写中写时复制的疑问 一、感到不理解的歧义 在部分技术文档中&#xff08;以小林的文章为例&#xff09;&#xff0c;对写时复制后的内存权限存在如歧义&#xff1a; ! 二、正确技术表述 根据Linux内核实现&#xff08;5.15版本&#x…...

【新手初学】SQL注入getshell

一、引入 木马介绍&#xff1a; 木马其实就是一段程序&#xff0c;这个程序运行到目标主机上时&#xff0c;主要可以对目标进行远程控制、盗取信息等功能&#xff0c;一般不会破坏目标主机&#xff0c;当然&#xff0c;这也看黑客是否想要搞破坏。 木马类型&#xff1a; 按照功…...

【湖北工业大学2025年ACM校赛(同步赛)】题解

比赛链接 A. 蚂蚁上树 题目大意 给定一棵 n n n 个结点的树&#xff0c;根结点为 1 1 1。每个 叶结点 都有一只蚂蚁&#xff0c;每过 1 1 1 秒钟&#xff0c;你可以选一些蚂蚁往其 父结点 走一步&#xff0c;但是要求任意两只蚂蚁都不能在同一个 非根结点 上。 问至少要…...

FPGA Verilog/VHDl 中的锁存latch

目录 一、前言二、锁存器定义三、verilog中锁存的产生四、verilog中锁存的影响和消除五、FPGA中的锁存器资源 一、前言 在做FPGA设计时&#xff0c;我们要求在组合逻辑设计时&#xff0c;case或者if-else条件要完整&#xff0c;否则会产生锁存。本文主要介绍锁存产生的原因和影…...

Ubuntu24.04 配置远程桌面服务

一&#xff1a;安装 sudo apt update sudo apt install vino 二&#xff1a;设置 gsettings set org.gnome.Vino require-encryption false # 关闭加密&#xff08;某些 VNC 客户端不支持加密&#xff09; gsettings set org.gnome.Vino prompt-enabled false # 关闭连接…...

【二刷代码随想录】螺旋矩阵求解方法、推荐习题

一、求解方法 &#xff08;1&#xff09;按点模拟路径 在原有坐标的基准上&#xff0c;叠加 横纵坐标 的变化值&#xff0c;求出下一位置&#xff0c;并按题完成要求。但需注意转角的时机判断&#xff0c;特别是最后即将返回上一出发点的位置。 &#xff08;2&#xff09;按层…...

Python基础教程:从格式化到项目管理

一、Typora代码块支持格式 在Typora中编写代码时&#xff0c;支持多种语言的语法高亮显示&#xff1a; 二、代码格式化 1. %格式化&#xff08;传统方式&#xff09; 第一种方式&#xff1a;正规方式 示例代码&#xff1a; name "张三" age 10 print("我的…...

Python爬虫:开启数据抓取的奇幻之旅(一)

目录 一、爬虫初印象&#xff1a;揭开神秘面纱​ 二、工欲善其事&#xff1a;前期准备​ &#xff08;一&#xff09;Python 环境搭建​ 1.下载 Python 安装包&#xff1a;​ 2.运行安装程序&#xff1a;​ 3.配置环境变量&#xff08;若自动添加失败&#xff09;&#x…...

分布式ID服务实现全面解析

分布式ID生成器是分布式系统中的关键基础设施&#xff0c;用于在分布式环境下生成全局唯一的标识符。以下是各种实现方案的深度解析和最佳实践。 一、核心需求与设计考量 1. 核心需求矩阵 需求 重要性 实现难点 全局唯一 必须保证 时钟回拨/节点冲突 高性能 高并发场景…...

浏览器与网络模块实践

浏览器渲染步骤 浏览器渲染大致分为以下四个步骤&#xff1a; 1. 构建 DOM 树 • 过程&#xff1a;当浏览器接收到 HTML 文档后&#xff0c;会从上到下依次解析 HTML 代码。每遇到一个开始标签&#xff0c;就会创建一个对应的 DOM 节点&#xff0c;并根据标签的嵌套关系将这些…...

谈谈Minor GC、Major GC和Full GC

目录 一、背景 二、三者之间的区分 1、Minor GC 2、Major GC &#xff08;1&#xff09;老年代空间不足&#xff1a; &#xff08;2&#xff09;晋升&#xff08;Promotion&#xff09;失败&#xff1a; &#xff08;3&#xff09;空间分配担保失败&#xff1a; &#x…...

基于SpringBoot实现的高校实验室管理平台功能四

一、前言介绍&#xff1a; 1.1 项目摘要 随着信息技术的飞速发展&#xff0c;高校实验室的管理逐渐趋向于信息化、智能化。传统的实验室管理方式存在效率低下、资源浪费等问题&#xff0c;因此&#xff0c;利用现代技术手段对实验室进行高效管理显得尤为重要。 高校实验室作为…...

梯度裁剪(Gradient Clipping)

梯度裁剪&#xff08;Gradient Clipping&#xff09;是一种用于防止梯度爆炸&#xff08;Gradient Explosion&#xff09;的技术&#xff0c;具体来说&#xff1a; 1. 梯度裁剪的作用 问题背景&#xff1a;在训练深度神经网络&#xff08;尤其是RNN/LSTM&#xff09;时&#x…...

联合办公空间WeWork的创新模式与私域流量时代的品牌温度——兼论开源AI大模型AI智能名片S2B2C商城小程序源码的潜在价值

摘要&#xff1a;本文聚焦于联合办公空间WeWork的成功模式&#xff0c;深入剖析其如何让创业用户摆脱传统租赁的束缚&#xff0c;打破空间与社交限制&#xff0c;为创业带来新的可能性与趣味性&#xff0c;并有效降低创业成本与风险。同时探讨了WeWork在私域流量时代所建立的平…...

Git配置

为什么要用&#xff1a;下载zip只是当前分支&#xff0c;不能进行仓库push、pull、checkout 1. 下载Git 先判断是否已经下过Git&#xff1a; git --version若没有版本号出来&#xff0c;就去下载&#xff1a;https://git-scm.com/downloads &#xff08;Windows、linux、mac…...