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

C++ 左值与右值(Lvalue/Rvalue)全解析

左值与右值是 C++ 表达式的核心分类,C++11 引入右值引用后进一步细化,是理解移动语义、完美转发的基础。以下从定义、判别、代码示例到高级引用全方位解析。

一、核心定义与判别标准

1. 左值(Lvalue)

**定义:**有名称、可寻址、生命周期持久的对象。
核心特征:

  • 可以使用取地址符 & 获取地址 ✅
  • 通常出现在赋值号左侧(也可在右侧)
  • 生命周期超过单个表达式
    **典型例子:**变量名、数组元素、解引用指针、返回左值引用的函数

2. 右值(Rvalue)

**定义:**临时值、无名称、即将销毁的对象。
核心特征:

  • 不可使用 & 获取地址 ❌
  • 通常出现在赋值号右侧
  • 生命周期仅限于当前表达式
    分类(C++11 起):
    **- 纯右值(prvalue):**纯粹的临时值,如字面量、算术表达式结果、临时对象
    **- 将亡值(xvalue):**即将被移动的对象,如 std::move 转换的结果
二、基础代码示例

1. 左值与右值的基本区分

#include<iostream>usingnamespacestd;intmain(){// 1. 基础定义:变量是左值,字面量是右值inta=10;// a 是左值(有名称、可寻址),10 是纯右值(临时字面量)intb=a;// a 作为右值使用(拷贝其值)// 2. 表达式结果是右值intc=a+b;// a + b 的结果是纯右值(临时计算值)// 3. 判别核心:能否取地址int*p1=&a;// ✅ 正确:a 是左值,可取值// int* p2 = &(a + b); // ❌ 错误:a + b 是右值,不可取地址// 4. 赋值操作左侧必须是左值// 10 = a; // ❌ 错误:10 是右值,不能放在赋值号左侧a=100;// ✅ 正确:a 是左值return0;}

2. 特殊案例:字符串字面量

// 字符串字面量是左值(特例)constchar*ptr="hello";// "hello" 是左值(存储在只读数据段,有地址)// &"hello" 是合法的 ✅
三、左值引用与右值引用

1. 左值引用(T&)

**定义:**对左值的别名,C++98 引入。
**规则:**只能绑定到非 const 左值(const 左值引用可绑定右值)。

#include<iostream>usingnamespacestd;intmain(){inta=10;// ✅ 正确:绑定到左值int&ref_a=a;ref_a=20;// 修改引用即修改原对象cout<<"a = "<<a<<endl;// 输出 20// ❌ 错误:普通左值引用不能绑定到右值// int& ref_b = 10;// ✅ 正确:const 左值引用可绑定右值(会延长临时对象生命周期)constint&ref_c=10;// ref_c = 20; // ❌ 错误:const 引用不可修改return0;}

2. 右值引用(T&&)

**定义:**C++11 引入,专门绑定到右值,支持移动语义。
**规则:**只能绑定到右值(纯右值/将亡值),需通过 std::move 绑定左值。

#include<iostream>#include<string>usingnamespacestd;intmain(){inta=10;// ✅ 正确:绑定到纯右值int&&ref_a=10;ref_a=20;// 可修改(右值引用是左值?不,这里是绑定的右值本身可修改)cout<<"ref_a = "<<ref_a<<endl;// 输出 20// ❌ 错误:不能直接绑定到左值// int&& ref_b = a;// ✅ 正确:std::move 将左值转为将亡值(右值)int&&ref_c=std::move(a);cout<<"a = "<<a<<", ref_c = "<<ref_c<<endl;// 输出:a = 10, ref_c = 10(a 状态变为“移后源”,但未销毁)return0;}
四、高级应用:移动语义(核心价值)

右值引用的核心用途是**避免大对象拷贝,**通过“移动”接管临时对象的资源(如堆内存、文件句柄)。

示例:自定义类的移动构造

#include<iostream>#include<cstring>usingnamespacestd;classMyString{private:char*data;size_t len;public:// 构造函数MyString(constchar*str){len=strlen(str);data=newchar[len+1];strcpy(data,str);cout<<"构造:分配内存 "<<(void*)data<<endl;}// 拷贝构造(深拷贝:性能低)MyString(constMyString&other){len=other.len;data=newchar[len+1];strcpy(data,other.data);cout<<"拷贝构造:深拷贝 "<<(void*)data<<endl;}// 移动构造(右值引用:性能高,接管资源)MyString(MyString&&other)noexcept{// 直接接管对方资源data=other.data;len=other.len;// 置空原对象,避免重复释放other.data=nullptr;other.len=0;cout<<"移动构造:接管资源 "<<(void*)data<<endl;}// 析构函数~MyString(){if(data){cout<<"析构:释放 "<<(void*)data<<endl;delete[]data;}}};intmain(){// 场景1:拷贝构造(绑定左值)MyStrings1("hello");MyString s2=s1;// 调用拷贝构造(深拷贝,性能低)// 场景2:移动构造(绑定右值)MyString s3=MyString("world");// MyString("world") 是纯右值// 编译器优化:直接在 s3 存储区构造,省略移动/拷贝// 场景3:强制移动(std::move)MyString s4=std::move(s1);// 调用移动构造(接管 s1 资源)return0;}

运行结果(关键)

plaintext

构造:分配内存 0x7f8b9a000010
拷贝构造:深拷贝 0x7f8b9a000030
构造:分配内存 0x7f8b9a000050
移动构造:接管资源 0x7f8b9a000010
析构:释放 0x7f8b9a000030
析构:释放 0x7f8b9a000010

**对比:**拷贝构造重新分配内存并复制数据,移动构造直接接管资源,大幅提升性能。

五、函数参数中的左值/右值匹配
#include<iostream>usingnamespacestd;// 1. 仅接受左值voidfunc_lvalue(int&val){cout<<"接收左值:"<<val<<endl;}// 2. 仅接受右值voidfunc_rvalue(int&&val){cout<<"接收右值:"<<val<<endl;}// 3. 万能接收(const 左值引用)voidfunc_both(constint&val){cout<<"接收左值/右值:"<<val<<endl;}intmain(){inta=10;func_lvalue(a);// ✅ 左值// func_lvalue(20); // ❌ 右值无法绑定到非 const 左值引用func_rvalue(20);// ✅ 右值// func_rvalue(a); // ❌ 左值无法绑定到右值引用func_both(a);// ✅ 左值func_both(20);// ✅ 右值(const 引用可延长临时对象生命周期)return0;}
六、核心总结表
特性左值(Lvalue)纯右值(Prvalue)将亡值(Xvalue)右值引用(T&&)
名称无(匿名)有(引用名)
取地址
赋值左侧
绑定对象持久对象临时值即将销毁对象右值(纯/将亡)
核心用途修改变量、传参字面量、表达式移动语义移动语义、完美转发

七、关键注意事项

  1. 右值引用本身是左值:定义了右值引用变量后,它在表达式中就是左值。
int&&a=10;// int&& b = a; // ❌ 错误:a 是左值,不能直接绑定到右值引用int&&b=std::move(a);// ✅ 正确:再次转为右值​```2.**std::move 不移动任何东西:**仅做类型转换,将左值转为右值,移动操作由移动构造/赋值函数完成。 ​3.**移动后源对象状态:**标准未强制要求,但通常变为“空、合法但未指定”状态,如 std::string 移动后变为空字符串。 ​4.**返回值优化(RVO):**编译器会自动优化临时对象,直接在目标存储区构造,省略移动/拷贝。
http://www.jsqmd.com/news/428730/

相关文章:

  • 腾讯应用宝创新服务模式,打造便捷高效移动应用新体验
  • 2026最新重庆会展策划公司权威推荐:3家实力企业助你高效落地 - 深度智识库
  • python+flask+vue框架的档案数字化项目沟通协作管理系统
  • 从“HALO交易”到电力系统智能化:霍尔电流传感器如何助力新能源革命?
  • 2026最新重庆活动策划公司排行榜:实力机构盘点与选择指南 - 深度智识库
  • 解锁语言潜能:2026年优选六大少儿英语培训机构推荐 - 品牌2026
  • python+flask+vue框架的电子政务服务预约管理系统
  • react基础讲义
  • 字典
  • 2026冷喂料橡胶挤出机品牌深度评测报告 - 优质品牌商家
  • 重庆校园文化建设公司推荐:2026年最新校方首选清单(附真实案例) - 深度智识库
  • 2026零基础烧烤加盟项目推荐榜低回本优选:特色烧烤加盟、知名烧烤品牌、自助烧烤加盟、适合小白的餐饮加盟选择指南 - 优质品牌商家
  • 2026汽车应急启动电源怎么选?全方位参数对比与选购建议 - 品牌2026
  • 元宇宙实验室哪家公司好?津发科技入选工信部元宇宙标准化工作组2025年度标准化工作先进集体、先进委员 - 品牌推荐大师1
  • 2026年全国有机肥厂家哪家口碑好?口碑出众且适配不同规模种植 - 深度智识库
  • 2026汽车电瓶设备公司推荐指南:如何挑选靠谱的汽车电瓶设备供应商? - 品牌2026
  • PHP的interface PaymentService {的庖丁解牛
  • 2026重庆展厅设计公司推荐:3家实力派清单,落地性拉满 - 深度智识库
  • 开源免费、部署简单的在线评测系统(OJ)
  • 锁相放大器SR830与OE1022性能对比分析
  • 零基础从零到一写一个 Hello World 级别的测试用例的庖丁解牛
  • nmn哪个牌子好高活性纯度2026年性价比高的十大nmn品牌榜推荐哪款? - 速递信息
  • ins代运营公司优选!海外社媒营销服务商+制造业海外推广获客服务商全攻略 - 品牌2026
  • 2026汽车电瓶设备出口厂商怎么选?跨境供货商与供应链服务商汇总 - 品牌2026
  • Nginx for Windows的使用
  • 直至云雨消散
  • 2026年冷喂料橡胶挤出机公司权威推荐:复合橡胶挤出机、橡胶挤出生产线、橡胶挤出硫化生产线、硅橡胶挤出机选择指南 - 优质品牌商家
  • 水质不达标?2026水处理设备厂家推荐排行 资质齐全/多水质处理 实用评测榜 - 极欧测评
  • 17.水流量计
  • VersionCheck.js - 让前端版本更新变得简单优雅