C++左值与右值及引用的总结


前言

在C++中,理解左值(lvalue)和右值(rvalue)是掌握现代C++核心特性的关键。左值通常指代具名的、持久存在的对象,可以取地址;而右值则是临时的、即将销毁的值,如字面量或表达式结果。引入右值引用(&&)后,引用(包括左值引用和右值引用)作为别名机制,避免了不必要的拷贝,同时为函数参数传递和返回值优化提供了灵活的选择。


一、值类别基础:理解左值与右值

在C++中,每个表达式都有两个关键属性:类型(type)值类别(value category)。值类别是C++表达式的重要特征,决定了表达式可以出现在代码中的位置以及其生命周期。

1.1 左值详解

左值是指那些有明确身份、有名字、持久存在的对象,其核心特征包括:

  • 可以取地址(使用&运算符)

  • 可以出现在赋值语句的左侧

  • 通常有变量名或解引用指针的结果

  • 生命周期超出单个表达式

#include<iostream>
using namespace std;
int& getRef() {static int val = 5;return val;  // 返回左值引用
}
int main()
{
int x = 10;     // x是左值
int* p = &x;    // 可以取地址
x = 20;         // 可以出现在赋值左侧int arr[5];
arr[0] = 1;     // 数组元素是左值getRef() = 10;  // 函数返回左值引用可作为左值
}

1.2 右值深入解析

右值代表临时对象即将销毁的对象,主要特点:

  • 不能取地址

  • 通常没有名字

  • 生命周期仅限于当前表达式

  • 包括字面量、临时对象和非引用返回的函数返回值

int x = 10;         // 10是右值
int y = x + 5;      // x+5的结果是右值
string s = "hello"; // "hello"是右值int func() { return 42; }
int z = func();     // func()返回右值

1.3 混合类别:广义左值(glvalue)和纯右值(prvalue)

C++11进一步细化了值类别:

  • 广义左值(glvalue):包括传统左值和xvalue(将亡值)

  • 纯右值(prvalue):传统右值概念

  • 将亡值(xvalue):生命周期即将结束但仍有身份的对象

std::string getString() { return "temp"; }
std::string&& r = getString(); // getString()返回xvalue

这里的函数返回一个临时 std::string 对象(存储值 "temp"

  • 这个临时对象属于将亡值(xvalue),具有以下特征:

  • 即将被销毁(表达式结束时 但仍有明确的内存地址和状态 可以被"延长寿命"

二、左值引用与右值引用

2.1 左值引用(传统引用)

左值引用使用&声明,只能绑定到左值:

int x = 10;
int& lref = x;    // 正确
int& lref2 = 10;  // 错误:不能绑定到右值const int& cref = 10; // 特殊规则:const左值引用可绑定右值

2.2 右值引用(C++11新特性)

右值引用使用&&声明,只能绑定到右值:

int&& rref = 10;      // 正确
int x = 5;
int&& rref2 = x;      // 错误:不能绑定左值
int&& rref3 = x + 3;  // 正确:x+3是右值std::string&& sref = getString(); // 绑定函数返回的右值

2.3 引用绑定规则总结

引用类型可绑定对象示例
T&左值int x; int& r = x;
const T&左值/右值const int& r = 10;
T&&右值int&& r = 10;
const T&&右值const int&& r = 10;

三、移动语义:右值引用的革命性应用

3.1 移动构造函数

class String {
public:// 移动构造函数String(String&& other) noexcept : data(other.data), size(other.size) {other.data = nullptr;  // 置空原对象other.size = 0;}private:char* data;size_t size;
};

3.2 移动赋值运算符

class String {
public:// 移动赋值运算符String& operator=(String&& other) noexcept {if (this != &other) {delete[] data;      // 释放现有资源data = other.data;  // 接管资源size = other.size;other.data = nullptr;other.size = 0;}return *this;}
};

3.3 移动语义的优势

  1. 避免不必要的拷贝:特别是对于大型对象

  2. 资源所有权转移:高效管理堆内存、文件句柄等

  3. 标准库优化:容器操作性能显著提升

4.常见陷阱与最佳实践

4.1 注意事项

  1. 不要返回局部变量的右值引用

std::string&& badExample() {std::string s = "hello";return std::move(s); // 危险!s将被销毁
}
  1. 移动后对象状态:应处于有效但未定义状态

  2. 标记移动操作为noexcept:帮助标准库优化

  3. 避免过度使用std::move:可能阻止RVO(返回值优化)


总结

左值/右值引用系统是C++现代编程的核心特性,理解它们能够:

  1. 显著提升程序性能(减少拷贝)

  2. 实现更优雅的资源管理

  3. 编写更安全高效的模板代码

  4. 充分利用标准库提供的优化

这套机制构成了C++高效编程的基础设施。建议通过实际项目练习来巩固这些概念,同时关注C++20/23对值类别系统的进一步改进。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/84403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习记录:DAY31

Java课设&#xff1a;数字水印处理与解析器开发 前言 想养成写日记的习惯真不容易。最近比较懒散&#xff0c;复习不想复&#xff0c;项目又做完了&#xff0c;处于一种能干些什么&#xff0c;但是不太想干&#xff0c;但是不干些什么又浑身难受的处境。其实完全就不是匀不出…

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…

系统模块与功能设计框架

系统模块与功能设计框架&#xff0c;严格遵循专业架构设计原则&#xff0c;基于行业标准&#xff08;如微服务架构、DDD领域驱动设计&#xff09;构建。设计采用分层解耦模式&#xff0c;确保可扩展性和可维护性&#xff0c;适用于电商、企业服务、数字平台等中大型系统。 系统…

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …

Prompt工程学习之自我一致性

自我一致性 &#xff08;Self-consistency&#xff09; 概念&#xff1a;该技术通过对同一问题采样不同的推理路径&#xff0c;并通过多数投票选择最一致的答案&#xff0c;来解决大语言模型&#xff08;LLM&#xff09;输出的可变性问题。通过使用不同的温度&#xff08;temp…

gh hugging face使用

install sudo dpkg -i gh_2.74.0_linux_amd64.deb gh auth login gh auth login ? Where do you use GitHub? GitHub.com ? What is your preferred protocol for Git operations on this host? HTTPS ? Authenticate Git with your GitHub credentials? Yes ? How wo…

2025.6.9总结(利与弊)

凡事都有两面性。在大厂上班也不例外。今天找开发定位问题&#xff0c;从一个接口人不断溯源到另一个 接口人。有时候&#xff0c;不知道是谁的责任填。将工作内容分的很细&#xff0c;每个人负责其中的一小块。我清楚的意识到&#xff0c;自己就是个可以随时替换的螺丝钉&…

数据集-目标检测系列- 口红嘴唇 数据集 lips >> DataBall

贵在坚持&#xff01; * 相关项目 1&#xff09;数据集可视化项目&#xff1a;gitcode: https://gitcode.com/DataBall/DataBall-detections-100s/overview 2&#xff09;数据集训练、推理相关项目&#xff1a;GitHub - XIAN-HHappy/ultralytics-yolo-webui: ultralytics-yo…

[论文阅读] 人工智能+项目管理 | 当 PMBOK 遇见 AI:传统项目管理框架的破局之路

当PMBOK遇见AI&#xff1a;传统项目管理框架的“AI适配指南” 论文信息 arXiv:2506.02214 Is PMBOK Guide the Right Fit for AI? Re-evaluating Project Management in the Face of Artificial Intelligence Projects Alexey Burdakov, Max Jaihyun Ahn Subjects: Software …

CentOS7关闭防火墙、Linux开启关闭防火墙

文章目录 一、firewalld开启、关闭防火墙1、查看防火墙状态 一、firewalld开启、关闭防火墙 以下命令在linux系统CentOS7中操作开启关闭防火墙 # 查询防火墙状态 systemctl status firewalld.service # 开启防火墙 systemctl start firewalld.service # 开机自启动防火墙 syste…

Spring是如何实现无代理对象的循环依赖

无代理对象的循环依赖 什么是循环依赖解决方案实现方式测试验证 引入代理对象的影响创建代理对象问题分析 源码见&#xff1a;mini-spring 什么是循环依赖 循环依赖是指在对象创建过程中&#xff0c;两个或多个对象相互依赖&#xff0c;导致创建过程陷入死循环。以下通过一个简…

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…

基于 Spring Boot 策略模式的短信服务提供商动态切换实现

一、整体设计思路 为了实现在短信服务提供商变更时,不修改现有代码就能无缝切换到新服务实现,可采用策略模式结合依赖注入以及配置中心化管理的方式来设计软件系统。 二、 具体实现步骤 1. 定义统一接口(以短信服务为例,接口命名为 SmsService) 创建一个抽象的接口,用…

解决SQL Server SQL语句性能问题(9)——SQL语句改写(1)

9.4. SQL语句改写 目前主流关系库的高版本中,特别是作为主流商业关系库的SQL Server来讲,大部分场景中,同一语义和结果集的SQL语句,其不同写法并不会影响CBO为SQL语句生成和选择最合适、最高效的查询计划。但少数情况下,不同写法的同一语义和结果集的SQL语句,CBO也许会为…

设计模式复习小结

1.容易忘得设计原则 接口隔离&#xff1a;指接口中的功能太杂则可以拆分一下。防止实现类实现了接口后自动依赖了一些不需要的功能。不同功能拆分成不同的接口。 里氏代换&#xff1a;强调父类能出现的地方&#xff0c;子类一定能正常跑。 迪米特法则&#xff1a;又称最少知…

昇腾CANN集合通信技术解读——细粒度分级流水算法

随着AI技术的演进&#xff0c;模型的计算复杂度和参数量呈现几何级数增长&#xff0c;这使得传统单机单卡部署在算力供给与显存容量方面显得力不从心&#xff0c;从而直接推动了分布式训练/推理技术的快速发展。今年年初爆火的DeepSeek在训练及推理Prefill阶段采用了分级流水Al…

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…