小学生学C++编程语法知识(C++左值和右值与右值引用)
左值有名字、可以找到它的东西。右值通常是临时产生、马上就要用完的东西。右值引用专门用来“接住那些马上要用完的东西”。std::move()告诉编译器“这个东西我不要原来的资源了你可以把它搬走”。一、先从“盒子”开始理解假设int a 10;我们可以把它想象成a ↓ ┌─────────┐ │ 10 │ └─────────┘a是一个有名字的盒子。我们可以a 20;也可以cout a;还可以int *p a;因为我们能够找到这个盒子在哪里。这种东西在 C 中叫左值lvalue二、什么是右值看看10或者a 5或者10 20它们通常是计算过程中产生的一个临时结果。比如int x a 5;计算a 5 ↓ 10 5 ↓ 15这个15是计算出来的临时结果。你可以把它想象成┌─────────┐ │ 15 │ └─────────┘ ↓ 马上交给 x它通常不是一个我们长期保存、随时可以找到的“盒子”。这种表达式产生的临时值属于右值rvalue三、先记住一个非常简单的口诀初学的时候可以这样记左值有名字的东西。右值临时产生的东西。例如int a 10;这里a → 左值 10 → 右值再看int b a 5;这里a → 左值 a 5 → 右值四、为什么叫“左值”和“右值”这是一个历史原因。我们经常看到a 10;a在等号左边a 10 ↑ ↑ 左 右所以以前很容易把左值 等号左边右值 等号右边。但是这种理解不够准确例如a b c;右边的b c确实是右值。但a b;右边的b仍然是左值所以“左值” ≠ “出现在等号左边” “右值” ≠ “出现在等号右边”这是初学者最容易踩的坑。五、一个更好的理解左值像“房子”我们可以把左值想象成 一个可以找到的房子例如int a 10;a就像一间有地址的房子a ↓ 10你可以a 20;把房子里的东西换掉。还可以a找到这间房子的地址。而a 5更像 一个临时包裹a 5 ↓ 15 ↓ 用完它主要是为了完成某个计算。所以左值 → 有身份、可以找到 右值 → 通常是临时结果这个理解比单纯记“左边右边”好很多。六、来看几个典型例子例1int a 10;a → 左值 10 → 右值例2int b a;这里b → 左值 a → 左值注意虽然a在等号右边它仍然是左值。例3int c a b;c → 左值 a → 左值 b → 左值 a b → 右值因为a b是计算产生的临时结果。七、函数返回值也很有意思例如int add(int a, int b) { return a b; }调用int x add(3, 5);add(3, 5)产生8这个8是一个临时结果。所以add(3, 5)通常可以作为右值。八、那么问题来了右值为什么需要“引用”我们以前学过int ref a;这叫左值引用它可以理解成给一个已经存在的房子取一个别名。例如int a 10; int ref a;现在a ↓ 10 ↑ refa和ref是同一个变量。所以ref 20;实际上就是a 20;九、可是普通引用不能直接绑定普通右值例如int ref 10;通常是不允许的。因为10是一个临时结果。你不能简单地说“我要给这个临时东西起一个普通左值引用。”所以 C11 引入了右值引用写法int ref 10;注意是一个而是两个十、右值引用到底是什么例如int ref 10;可以简单理解成ref是一个专门用来接住右值的引用。图像化临时值 10 ↓ ┌─────────┐ │ 10 │ └─────────┘ ↑ │ ref所以int ref 10;就是“我允许ref接住这个临时值。”十一、为什么C需要右值引用这就回到我们上一节讲的移动构造函数假设class Box { public: int *data; Box(int n) { data new int[n]; } };现在Box a(1000000);a里面有大量资源a │ └────────→ [100万个数据]如果Box b a;通常意味着我要复制一份。于是a ─────→ [100万个数据] b ─────→ [重新复制的100万个数据]很慢。但是如果Box b 某个马上不用的Box;那么我们完全可以说“既然这个对象马上就不用了干嘛还复制直接把资源搬过来吧”这就是移动语义而 C 需要一个办法区分这个对象以后还要不要于是T表示这是一个左值我还要继续使用。而T表示这是一个右值它通常是临时的可以考虑移动它的资源。十二、这就是移动构造函数为什么写例如class Box { public: int *data; Box(Box other) { data other.data; other.data nullptr; } };看到Box other可以先理解为“我接收一个可以被搬走资源的Box。”然后data other.data;资源搬过来。再other.data nullptr;原来的对象放弃资源。于是移动前 other │ └────→ 移动后 other │ └────→ 空 新对象 │ └────→ 十三、但是有一个特别容易让人困惑的问题看看int a 10; int r a;你可能会想a不是有名字吗它是左值为什么不能绑定到右值引用答案是不能直接这样绑定。因为a是左值。而int需要右值。但是int r std::move(a);可以。这就引出了今天最重要的东西std::move()十四、std::move()到底是什么很多初学者第一次看到std::move(a)会产生一个误解“是不是把a的数据搬走了”其实不是这是一个非常重要的知识点。std::move()本身通常并不真正搬运数据。它做的事情更像“贴一个标签”例如Box a(1000000);原来a ↓ a本身是左值。调用std::move(a)相当于告诉编译器“我允许你把a当成一个可以移动资源的对象。”所以a │ ├── 本身仍然是a │ └── 只是表达式被转换成“右值形式”十五、一个特别重要的口诀请孩子一定记住std::move()不是搬家公司。它更像是“搬家许可证”。它告诉程序“这个对象我后面不再依赖它原来的资源了可以考虑把资源搬走。”真正搬东西的是移动构造函数例如Box b(std::move(a));发生的是std::move(a) ↓ “a可以被移动” ↓ 匹配 Box(Box) ↓ 移动构造函数真正接管资源 ↓ 资源发生转移十六、看看最经典的例子class Box { public: int *data; Box(int n) { data new int[n]; } Box(const Box other) { cout 拷贝构造 endl; // 这里应该复制数据 } Box(Box other) { cout 移动构造 endl; data other.data; other.data nullptr; } };然后Box a(1000000);现在a ↓ 100万个数据如果Box b(a);a是左值。所以更适合Box(const Box)也就是a ↓ 复制 ↓ b如果Box b(std::move(a));那么std::move(a) ↓ 告诉编译器a可以移动 ↓ Box(Box) ↓ 接管资源变成a ↓ 空 b ↓ 100万个数据十七、所以std::move()为什么能让移动构造函数被调用现在我们可以完整回答这个问题了。假设有Box a;直接Box b(a);这里a是左值于是编译器寻找适合左值的构造函数Box(const Box)而Box b(std::move(a));std::move(a)把表达式转换成右值更准确地说是xvalue于是Box(Box)这个移动构造函数就成为合适的匹配。所以a │ │ 左值 ↓ ┌─────────┐ │ 拷贝构造 │ └─────────┘ std::move(a) │ │ 右值形式 ↓ ┌─────────┐ │ 移动构造 │ └─────────┘十八、这里有一个进阶知识右值不只有一种如果以后看到 C 教材说左值、纯右值、将亡值不要害怕。C11之后值类别实际上可以分成表达式 │ ┌────────┴────────┐ │ │ 左值 右值 │ ┌────────┴────────┐ │ │ 纯右值 将亡值 prvalue xvalue初学阶段可以这样理解左值有身份、可以找到的对象。例如int a; a纯右值比较典型的临时值10 a b a * b将亡值它是一个已经存在但资源可以被“搬走”的对象。最典型的例子std::move(a)所以严格来说std::move(a)并不是把a变成一个“纯右值”而是把它转换成一个将亡值xvalue。对于小学生第一遍学习时记住std::move(a)让a变成“可以被移动”的右值形式。就足够了。十九、一个特别重要的坑std::move()之后还能不能使用原对象例如Box a(1000000); Box b(std::move(a));移动之后a → 资源已经被b接管 b → 拥有原来的资源那么cout a.data;能不能写这里要非常小心。移动后的对象仍然是一个有效对象但它的具体内容通常处于“有效但未指定”的状态。所以不要假设a还保持原来的数据。对于自己设计的移动构造函数我们通常会让它变成a.data nullptr;因此移动之后可以销毁它也可以重新给它赋值但不要依赖它还保留原来的资源或值。这也是为什么std::move(a);应该表达一个明确意图“a接下来不再需要原来的资源了。”二十、左值引用和右值引用放在一起比较现在把它们放一起int a 10; int r1 a; int r2 std::move(a);可以这样理解a │ ├── r1左值引用 │ └── r2右值引用它们最大的区别左值引用T右值引用T主要绑定左值右值典型用途给已有对象取别名移动语义是否可以修改通常可以通常可以典型例子int raint rstd::move(a)二十一、为什么普通的int也可以移动你可能会问int a 10; int b std::move(a);移动有什么意义其实对于int这种很小的数据移动和复制几乎没有区别。因为int ↓ 4字节左右复制一下非常快。移动语义真正厉害的地方是大数组 vector string 动态内存 文件句柄 大型资源这些资源。例如vectorint a(10000000); vectorint b std::move(a);这里移动就非常有价值。因为不需要重新复制1000万个元素。二十二、vector就是最好的现实例子例如vectorint a(1000000);大概可以想象a │ └────────→ [100万个int]然后vectorint b std::move(a);更像移动前 a ─────→ [100万个int] 移动后 a ─────→ 空/有效但未指定状态 b ─────→ [原来的100万个int]而不是a ─────→ [100万个int] b ─────→ [重新复制100万个int]所以移动语义的核心价值就是避免不必要的昂贵复制。二十三、把整个知识串起来现在我们终于可以把左值 → 右值 →→std::move()→ 移动构造全部串起来。C对象 │ ┌───────┴───────┐ │ │ 左值 右值 │ │ “我还要用” “临时/可以搬” │ │ T T │ │ │ 移动构造函数 │ │ │ ↓ │ 接管资源 │ │ └───────────────┘而std::move(a)就是在中间搭了一座桥a │ │ 左值 │ ▼ std::move(a) │ │ 转换成可移动的右值形式 │ ▼ 移动构造函数 │ ▼ 资源转移二十四、最后用一个“搬家故事”彻底记住假设小明有一辆玩具车小明 │ └── 小明还要继续玩就是一个左值因为它是小明正在使用、可以找到的东西。有一天小明决定“这辆车我不要了送给小红。”于是std::move(car)相当于小明宣布“这辆车可以搬走了”然后移动构造函数Car(Car other)相当于搬家公司来了把车直接搬给小红。最后小明 │ └── 空 小红 │ └── 注意std::move()不是搬家公司。它只是“允许搬家”的通知。真正执行资源转移的是移动构造函数。⭐ 最终记忆口诀我建议小朋友把下面这几句话背下来① 什么是左值有身份、能找到、通常可以长期使用的对象。例如int a 10; a② 什么是右值通常是临时产生的值或者可以把资源交出去的对象。例如10 a b③T是什么左值引用给一个已有对象起别名。int r a;④T是什么右值引用专门接住右值最重要的用途之一就是实现移动语义。int r 10;⑤std::move()是什么它不是搬东西而是告诉编译器“这个对象的资源可以被搬走。”std::move(a)⑥ 移动构造函数是什么接管资源而不是重新复制资源。Box(Box other) { data other.data; other.data nullptr; } 一张图总结a │ │ 左值 │ │ std::move(a) ↓ 可移动的右值 │ ↓ T │ ↓ 移动构造函数 │ ↓ 接管资源 │ ┌────────┴────────┐ ↓ ↓ 新对象 a 拿到资源 放弃资源真正理解这张图就已经把C11 移动语义最核心的逻辑串起来了左值 “我还要用它”右值 “它可以被拿走/通常是临时结果” “我可以接收可移动对象”std::move() “我允许你把它当成可移动对象”移动构造 “那我就把资源直接接过来”。

相关新闻

CTF栈溢出实战:Ret2Text攻击技术与后门函数利用

CTF栈溢出实战:Ret2Text攻击技术与后门函数利用

1. 题目背景与核心概念解析 这道来自CTFshow平台的pwn036题目,是典型的栈溢出利用场景,主要考察Ret2Text(Return to Text)攻击技术和后门函数利用能力。在CTF竞赛中,这类基础题型出现频率高达60%以上,是二进…

2026/10/18 4:34:02 阅读更多 →
Ubuntu系统资源监控实战:从CPU、内存到网络的全面排查指南

Ubuntu系统资源监控实战:从CPU、内存到网络的全面排查指南

1. 引言:为什么你需要掌握系统资源监控如果你在Ubuntu上跑过服务、部署过应用,或者仅仅是觉得电脑突然变慢了,那你大概率遇到过这样的场景:终端里敲命令,响应慢得像在爬;浏览器开几个标签页,风扇…

2026/10/18 4:34:17 阅读更多 →
深入理解MBR:计算机启动原理与512字节引导程序编写实战

深入理解MBR:计算机启动原理与512字节引导程序编写实战

1. 从零到一:理解MBR与计算机启动的“第一声啼哭”当你按下电脑的电源键,屏幕从一片漆黑到亮起Logo,再到进入熟悉的操作系统界面,这背后是一场精密而有序的接力赛。而这场接力赛的第一棒,就是我们今天要深入探讨的主角…

2026/10/17 22:02:18 阅读更多 →

最新新闻

国庆AI行业盘点:模型更新、开源生态与智能体落地加速

国庆AI行业盘点:模型更新、开源生态与智能体落地加速

国庆长假这两天,AI圈跟过年似的。10月1日到10月8日,前后八天,不断有模型更新、开源仓库爆点、智能体应用密集落地。作为一个长期跟踪这条赛道的人,我几乎每天都要刷好几遍测试榜单和社区讨论串,很多信息还没来得及沉淀…

2026/10/18 5:37:42 阅读更多 →
程序员必备20个网站:技术阅读、刷题、接单与效率工具盘点

程序员必备20个网站:技术阅读、刷题、接单与效率工具盘点

程序员必备网站这个老话题,几乎每隔几个月就会被重新拿出来聊一轮。技术、接单、刷题这三类网站,每个开发者的收藏夹里都躺着不止一个,但真到要用的时候,很多人会发现:收藏了 300 个网站,能稳定打开、准时解…

2026/10/18 5:37:42 阅读更多 →
全大写提示词触发AI风控?解析Claude互审封禁真相与安全写法

全大写提示词触发AI风控?解析Claude互审封禁真相与安全写法

有意思。“让Claude管Claude”本身没问题,问题是这句提示词是用全大写敲出来的。我是在一个技术讨论群里看到这件事的:某人做了个自动化流程,让一个Claude会话去审核另一个Claude会话生成的文案,这本来是个很常见的质检思路&#…

2026/10/18 5:37:42 阅读更多 →
Image GPS Editor实战:照片GPS数据的读取、修改与批量处理

Image GPS Editor实战:照片GPS数据的读取、修改与批量处理

前阵子帮朋友整理一趟长途自驾的素材,几百张照片导进电脑,结果发现相机里明明开了GPS记录,出来的照片却有一大半坐标信息是空的。另一批用手机拍的照片倒是带位置,但其中有几张因为当时在船上漂着,定位偏到了海里。用看…

2026/10/18 5:37:42 阅读更多 →
变量之路:理清编译与链接中的符号、地址与重定位机制

变量之路:理清编译与链接中的符号、地址与重定位机制

先问一个问题:你在 IDE 里写了int counter 0;,点一下运行按钮,程序跑起来了。可是那个叫counter的变量,它的地址到底是谁给它的?它为什么能从一个名字变成一个真实存在于内存里的地址?我在带新人的时候发现…

2026/10/18 5:37:42 阅读更多 →
律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

1. 这个系统到底在解决什么问题做律师的朋友应该都有过这种体验:一个案子从收到材料到最终归档,中间要经过立案、排期、取证、文书起草、审核、盖章、送达、开庭、归档这么一串流程。传统做法是什么?微信群接龙、Excel表格、共享文件夹、Outl…

2026/10/18 5:36:42 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →