【C++】 C++11:左值、右值,移动语义与完美转发
目录一、左值与右值二、左值引用的短板三、右值引用与移动语义移动语义变“复制”为“窃取”移动构造与移动赋值示例四、强制“窃取”std::move() 的妙用五、完美转发与 std::forward1. 披着右值皮的“万能引用”2. 属性退化的痛点3. std::forward 完美转发总结核心考点在 C 的学习路线上C11 是一次极其重要的进化。相比于 C98/03C11 包含了约 140 个新特性能更好地用于系统开发和库开发提升程序员的开发效率。而在这些新特性中右值引用和移动语义无疑是最核心、也是最能带来性能飞跃的语法特性。一、左值与右值在了解引用之前我们必须先分清什么是“左值”什么是“右值”左值是一个表示数据的表达式如变量名或解引用的指针。我们可以获取它的地址可以对它赋值。左值可以出现在赋值符号的左边。右值也是一个表示数据的表达式如字面常量、表达式返回值、函数返回值等。右值不能出现在赋值符号左边不能取地址。inta10;// a 是左值10 是右值int*pnewint(0);// p 和 *p 是左值intba10;// a 10 的结果是一个右值二、左值引用的短板传统的 C 语法中就有引用的语法C11 中新增了右值引用语法特性因此我们之前学习的引用就叫做左值引用使用表示。无论左值引用还是右值引用都是给对象取别名。左值引用在做函数参数和做返回值时都可以提高效率。但是它有一个致命的短板当函数返回对象是一个局部变量出了函数作用域就不存在了就不能使用左值引用返回只能传值返回。stringto_string(intvalue){string str;// ... 将 value 转换为字符串放入 strreturnstr;// 出作用域 str 被销毁只能传值返回}传值返回会导致至少 1 次拷贝构造如果是一些旧一点的编译器可能是两次拷贝构造。对于包含大量堆内存数据的容器或字符串这种深拷贝极其拖累程序效率。三、右值引用与移动语义为了补齐左值引用的短板C11 提出了右值引用使用表示也就是对右值的引用给右值取别名。intrr110;doublerr2xy;移动语义变“复制”为“窃取”有了右值引用我们可以增加移动构造和移动赋值函数。移动构造本质是将参数右值的资源窃取过来占位已有那么就不用做深拷贝了。所以它叫做移动构造就是窃取别人的资源来构造自己从而提高效率。移动构造与移动赋值示例在自定义string类中移动构造和移动赋值是这样工作的// 拷贝构造深拷贝性能开销大string(conststrings):_str(nullptr){stringtmp(s._str);swap(tmp);}// 移动构造窃取资源快如闪电string(strings):_str(nullptr),_size(0),_capacity(0){// 直接调用 swap 交换指针接管资源swap(s);}// 移动赋值窃取资源stringoperator(strings){swap(s);return*this;}intmain(){bit::string retbit::to_string(1234);//调用移动构造bit::string ret1;ret1bit::to_string(1234);//调用移动构造和移动赋值return0;}当执行bit::string ret bit::to_string(1234);时编译器会识别出to_string的返回值是一个右值如果既有拷贝构造又有移动构造调用就会匹配调用移动构造没有新开空间拷贝数据所以效率提高了。当执行bit::string ret1; ret1 bit::to_string(1234);时我们看到调用了一次移动构造和一次移动赋值。因为如果是用一个已经存在的对象接收编译器就没办法优化了。bit::to_string函数中会先用str生成构造生成一个临时对象但是我们可以看到编译器很聪明的在这里把str识别成了右值调用了移动构造。然后在把这个临时对象做为bit::to_string函数调用的返回值赋值给ret1这里调用的移动赋值。STL中的容器都是增加了移动构造和移动赋值四、强制“窃取”std::move() 的妙用按照语法右值引用只能引用右值。但当我们需要用右值引用去引用一个左值实现移动语义时可以通过std::move()函数将左值转化为右值。C11 中的std::move()函数名字具有迷惑性它并不搬移任何东西唯一的功能就是将一个左值强制转化为右值引用然后实现移动语义。strings1(hello world);// 我们把 s1 move 处理以后会被当成右值调用移动构造strings3(std::move(s1));// 警告这里要注意一般不要这样用因为 s1 的资源被转移给了 s3s1 被置空了五、完美转发与 std::forward当我们把右值引用和模板结合在一起时会发生一些奇妙的化学反应。在这里我们必须要了解一个概念万能引用与完美转发。1. 披着右值皮的“万能引用”在模板中并不总是代表右值引用。模板中的是万能引用其既能接收左值又能接收右值。templatetypenameTvoidPerfectForward(Tt){// 这里的 t 既能接收左值也能接收右值}2. 属性退化的痛点模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力。但是这里存在一个巨大的坑引用类型的唯一作用就是限制了接收的类型后续使用中都退化成了左值。也就是说即使你给PerfectForward传了一个右值在函数内部t有了名字它可以被取地址它本身就变成了一个左值。如果我们在这时继续把t传给底层的其他函数底层函数永远只会把它当成左值处理原本的右值属性丢失了移动语义也就无法触发。3. std::forward 完美转发我们希望能够在传递过程中保持它的左值或者右值的属性就需要用完美转发。C11 提供了std::forward。std::forwardT(t)在传参的过程中保留对象原生类型属性如果你原来是左值传下去还是左值如果你原来是右值传下去依旧是右值。voidFun(intx){cout左值引用endl;}voidFun(intx){cout右值引用endl;}templatetypenameTvoidPerfectForward(Tt){// std::forwardT(t) 在传参的过程中保持了 t 的原生类型属性Fun(std::forwardT(t));}intmain(){inta10;PerfectForward(a);// a 是左值Fun 会打印 左值引用PerfectForward(std::move(a));// move(a) 是右值Fun 会打印 右值引用return0;}完美转发在 STL 的很多底层实现比如可变参数模板、emplace_back等中被大量使用它是 C11 高效泛型编程的基石。总结核心考点左值引用只能引用左值但const左值引用既可引用左值也可引用右值其短板是当函数返回局部对象时只能传值返回。右值引用只能引用右值但是可以引用 move 以后的左值。移动构造/移动赋值本质是将参数右值的资源窃取过来不用做深拷贝完美解决了传值返回导致的性能瓶颈。std::move()的唯一功能就是将一个左值强制转化为右值引用用于实现移动语义。

相关新闻

电容器跳闸原因分析与预防维护全攻略

电容器跳闸原因分析与预防维护全攻略

1. 电容器跳闸问题的典型表现与初步判断当配电系统中电容器出现跳闸时,通常伴随着以下可观察现象:配电柜中电容器支路的断路器或熔断器动作断开,功率因数表显示数值异常下降(可能从0.95骤降至0.8以下),同时…

2026/9/26 5:09:09 阅读更多 →
MicroPython条件与循环:嵌入式编程的逻辑基石与实战技巧

MicroPython条件与循环:嵌入式编程的逻辑基石与实战技巧

1. 从“顺序执行”到“智能决策”:为什么需要条件与循环?写代码,本质上是在教计算机做事。最开始,我们写的代码就像一份简单的食谱清单,计算机从上到下,一行一行地执行,这就是“顺序执行”。比如…

2026/10/12 20:11:58 阅读更多 →
git操作命令

git操作命令

1 首次克隆 代码git clone 2 查询本地状态git status3 添加缓存 添加指定文件git add <文件名>添加 所有git add .删除缓存1 不会删除物理文件&#xff0c;只是将已经add的文件删除git rm --cached <文件名 >2 从缓存区删除某一个目录下所有文件git rm -r --cach…

2026/9/26 2:24:59 阅读更多 →

最新新闻

连接器可靠性试验:振动、冲击、碰撞三者的区别与工程选择

连接器可靠性试验:振动、冲击、碰撞三者的区别与工程选择

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 6:42:49 阅读更多 →
AnyPS5跨平台串流实战:主机编码、网络传输与客户端解码全解析

AnyPS5跨平台串流实战:主机编码、网络传输与客户端解码全解析

1. 从“AnyPS5”这个标题说起&#xff1a;一个跨平台串流工具的设计野心第一次看到“AnyPS5”这个命名&#xff0c;我的直觉是&#xff1a;这大概率是一个围绕主机游戏串流展开的项目&#xff0c;而且“Any”这个前缀暗示了它的核心卖点——跨平台、跨设备、尽可能抹平硬件壁垒…

2026/10/13 6:42:49 阅读更多 →
谱减法语音增强实战:从原理到参数调优的完整指南

谱减法语音增强实战:从原理到参数调优的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 6:42:49 阅读更多 →
PS5兼容性研究实战:状态识别、工具链匹配与恢复兜底

PS5兼容性研究实战:状态识别、工具链匹配与恢复兜底

我知道很多人看到“AnyPS5”这个名字&#xff0c;第一反应八成是“是不是所有PS5都能折腾了”。但真正在软硬件研究这个圈子里待过一段时间你就明白&#xff0c;“能否折腾”只是结果&#xff0c;背后真正值钱的是兼容性研究那一整套逻辑。不同型号的主板布局不一样&#xff0c…

2026/10/13 6:42:49 阅读更多 →
Windows下PyCharm连接Anaconda:虚拟环境与解释器配置全攻略

Windows下PyCharm连接Anaconda:虚拟环境与解释器配置全攻略

简介&#xff1a;Windows环境下在PyCharm中配置Anaconda开发环境&#xff0c;是不少Python初学者和数据科学入门者常遇到的痛点。这份超详细教程面向上述读者&#xff0c;清晰梳理了Python、PyCharm与Anaconda三者各自的角色与协作关系&#xff0c;并针对安装、导入、包管理过程…

2026/10/13 6:42:49 阅读更多 →
FPGA入门必做:可逆计数器设计详解与上板调试

FPGA入门必做:可逆计数器设计详解与上板调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 6:41:49 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →