C++左值/右值/左值引用/右值引用

1)C++入门级小知识,分享给将要学习或者正在学习C++开发的同学。

2)内容属于原创,若转载,请说明出处。

3)提供相关问题有偿答疑和支持。

左值和右值的概念:

早期的c语言中关于左值和右值的定义:
左值是可以位于赋值运算符"="左侧的表达式(当然,左值也可以位于"="的右侧);
右值是不可以位于赋值运算符 "="左侧的表达式;

区分左值和右值的一个简单办法是:看能不能对表达式取地址,如果能,则为左值、当然也可以充当右值,如果不能为右值。

如下:

int a;
int b;
a = b;
b = a;
以上a和b都可以位于运算符=的左侧,因此a,b都是左值;

int c;
c = 100; //ok
100 = c; //err
以上常量100只能位于运算符=的右侧因此常量100是右值

不过在 C++ 里面,左值和右值不能这样定义。根据《C++ Primer》的说法,左值和右值可以这样区分:
一个表达式是左值还是右值,取决于我们使用的是它的值还是它在内存中的位置(作为对象的身份)。
也就是说一个表达式具体是左值还是右值,要根据实际在语句中的含义来确定。

如下:
int foo=100;
int bar;

// 将 foo 的值赋给 bar,保存在 bar 对应的内存中
// foo 在这里作为表达式是右值;bar 在这里作为表达式是左值
// 但是 foo 作为对象,既可以充当左值又可以充当右值
bar = foo;

因为 C++ 中的对象本身可以是一个表达式,所以这里有一个重要的原则,即
在大多数情况下,需要右值的地方可以用左值来替代,但需要左值的地方,一定不能用右值来替代。

又有一个重要的特点,即
左值存放在对象中,有持久的状态;而
右值要么是字面常量,要么是在表达式求值过程中创建的临时对象,没有持久的状态

左值引用和右值引用的概念:
左值引用是常见的引用,所以一般在提到「对象的引用」的时候,指得就是左值引用。
如果我们将一个对象的内存空间绑定到另一个变量上,那么这个变量就是左值引用。
在建立引用的时候,我们是将内存空间绑定,因此我们使用的是一个对象在内存中的位置,这是一个左值。
因此,我们不能将一个右值绑定到左值引用上。另一方面,由于常量左值引用保证了我们不能通过引用改变对应内存空间的值,因此我们可以将右值绑定在常量引用上。

如下是左值引用:(左值引用只能绑定到左值上,const引用除外)
int foo=42;
int& bar = foo;  // OK: foo 在此是左值,将它的内存空间与 bar 绑定在一起
int& baz = 42;   // Err: 42 是右值,不能将它绑定在左值引用上
const int& qux = 42;  // OK: 42 是右值,但是编译器可以为它开辟一块内存空间,绑定在 qux 上


c++11中新加了右值引用&&:
对右值进行绑定的引用就是右值引用,他的语法是这样的A&&,通过双引号来表示绑定类型为A的右值。通过&&我们就可以很方便的绑定右值了;
如下是右值引用:(右值引用也是引用,但是它只能且必须绑定在右值上)。
int foo=42;
int& bar = foo;        // OK: 将 foo 绑定在左值引用上
int&& baz = foo;       // Err: foo 可以是左值,所以不能将它绑定在右值引用上
int&& qux = 42;        // OK: 将右值 42 绑定在右值引用上
int&& quux = foo * 1;  // OK: foo * 1 的结果是一个右值,将它绑定在右值引用上
int& garply = foo++;   // Err: 后置自增运算符返回的是右值,不能将它绑定在左值引用上
int&& waldo = foo--;   // OK: 后置自减运算符返回的是右值,将它绑定在右值引用上

由于右值引用只能绑定在右值上,而右值要么是字面常量,要么是临时对象,所以:
右值引用的对象,是临时的,即将被销毁;并且
右值引用的对象,不会在其它地方使用。

我们思考一个问题:右值引用本身是左值还是右值?或者可以先思考一下它的对偶问题:左值引用本身是左值还是右值?

先看下面的代码:
int foo(42);
int& bar = foo;     // bar 是对 foo 的左值引用
int& baz = bar;     // baz 是对 bar 的左值引用,因而 bar 是右值
int qux = ++foo;    // 前置自增运算符返回左值引用,在这里赋值给 qux,此时左值引用作为右值
观察上面代码,不难发现,左值引用本身既可以是左值,又可以是右值。它具体是左值还是右值,依然取决于它作为表达式时候的作用。更仔细地观察可以发现,
如果左值引用作为一个变量被保存下来了,那么它就可以是左值(当然也可以起到右值的作用);而如果左值引用是一个临时变量(例如函数的返回值),那么它就是右值。

同理可以用在右值引用上。

class Type;
void foo(Type&& bar) {
    // 将右值引用作为 Type 的构造函数的参数
    // 此时匹配 Type::Type(const Type& orig), 即拷贝构造函数
    // bar 是左值
    Type baz(bar);
}
Type&& qux();
quux = qux();   // qux 的返回值是 Type 类型的右值引用,此时右值引用是右值
和左值引用一样,右值引用本身也既可以作为左值也可以作为右值。并且,同样的是:如果右值引用作为变量被保存下来了,那么应该把它当做是一个左值看待;否则应当作为右值看待。

因此,不论是左值引用还是右值引用,都有

当引用作为变量被保存下来,那么它是左值;否则
它是右值。

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

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

相关文章

Kithara常见问题解答

目录 通用问题我的内核驱动程序已经签名了吗?是否可以在打开驱动程序时防止显示介绍窗口?Windows 7 仍然支持吗?错误0x10142422(KSERROR_CANNOT_START_KERNEL)在KS_openDriver时出现?错误 10145241 (KSERROR_CANNOT_START_KERNEL)…

低代码开发技术助力企业数字化管理的实践探究

随着信息技术的飞速发展,企业对于数字化管理的需求日益迫切。而低代码开发技术,以其高效、灵活、易用的特点,正逐渐成为企业数字化管理的重要工具。本文将进一步探讨低代码开发技术在企业数字化管理实践中的应用及其带来的变革。 低代码开发技…

每日一题——Python实现PAT乙级1026 程序运行时间(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 代码结构和逻辑 时间复杂度 空间复杂度 代码优化建议 总结 我要更强 …

交换机需要多大 buffer

有点违背直觉,但是真事儿,交换机过境的流越多,所需 buffer 越小,这是为什么? 范氏(范雅各布森,van jacobson)管道的 aimd 流建议 buffer_size 为 bdp,这很容易理解,因为 aimd 流最小…

【mybatis】spring boot框架中使用mybatis-plus配置多数据源

1、简介 在Java开发中,当使用MyBatis-Plus进行数据库操作时,可能会遇到需要配置多数据源的场景,比如读写分离、操作多个数据库等。MyBatis-Plus本身是基于MyBatis的增强工具,它并没有直接提供多数据源的配置支持,但可…

k8s nfs配置mysql,redis

1.安装nfs # centos yum install nfs-utils -ysudo mkdir -p /nfs/mysql sudo chmod 777 /nfs/mysqlsudo mkdir -p /nfs/redis sudo chmod 777 /nfs/redisvim /etc/exports/nfs/mysql *(rw,sync,no_root_squash) /nfs/redis *(rw,sync,no_root_squash)sudo exportfs -asystemc…

币界网讯,预计以太坊现货 ETF 将于 7 月中旬推出

刚刚 ETF Store 总裁 Nate Geraci 在 X (前Twitter)平台上宣布,备受数字货币市场期待的SEC以太坊现货 ETF提案,将于7 月中旬通过美国证券交易委员会(SEC)批准。Nate Geraci透露修订后的 S-1 文件将于 7 月 …

cannot import name ‘LineString‘ from ‘shapely‘

cannot import name LineString from shapely pip install shapely -U 升级到2.0后好像好了

【VUE】 深入理解 Vue 动态路由:简介、实际开发场景与代码示例

深入理解 Vue 动态路由:简介、实际开发场景与代码示例 Vue.js 是一个用于构建用户界面的渐进式框架,它拥有丰富的生态系统,其中 Vue Router 是其官方的路由管理库。动态路由是 Vue Router 的一个强大特性,允许我们在应用运行时根…

pnpm的坑

请问pnpm的两个坑怎么解决: 第一个坑:没有节省磁盘空间 我已经配置了依赖的存储位置, 但我在项目里pnpm install以后,发现依赖包还是很大, 然后发现里面的链接并不是指向先前配置的依赖存储位置,而是指…

【数智化人物展】袋鼠云CEO宁海元:大模型时代,Data+AI将成为新的基础设施

宁海元 本文由袋鼠云CEO宁海元投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 身处这个瞬息万变的数字经济时代,传统的生产模式往往依赖于经验和固定的流程&…

上海市计算机学会竞赛平台2023年2月月赛丙组圆环三染色

题目描述 有一个圆环上有 𝑛n 个点,一个染色方案需要为每个点分配三种颜色中的一种,且圆环上相邻的点颜色不能相同。 请求出有多少种染色方案。答案可能很大,输出模 1,000,000,0071,000,000,007 的余数。 输入格式 单个整数表…

k8s-第六节-数据持久化

数据持久化 kubernetes 集群不会为你处理数据的存储,需要为数据库挂载一个磁盘来确保数据的安全。 可以选择云存储、本地磁盘、NFS。 本地磁盘:可以挂载某个节点上的目录,但是这需要限定 pod 在这个节点上运行 云存储:不限定节…

GEE计算遥感生态指数RESI

目录 RESI湿度绿度热度干度源代码归一化函数代码解释整体的代码功能解释:导出RSEI计算结果参考文献RESI RSEI = f (Greenness,Wetness,Heat,Dryness)其遥感定义为: RSEI = f (VI,Wet,LST,SI)式中:Greenness 为绿度;Wetness 为湿度;Thermal为热度;Dryness 为干度;VI 为植被指数…

文心一言指令:快速入门手册

文心一言(Wenxin Yiyan)是百度推出的一款人工智能语言模型,能够生成自然语言内容,回答问题,进行翻译等多种任务。以下是详细的文心一言指令使用指南,帮助您快速上手。 目录 简介注册与登录接口调用常用指…

手写starter核心思路流程-全网最详细版本

全网最详细手写starter组件教程 那么在写这篇博客之前,先问一下大家为什么要写starter组件,仅仅只是为了炫技吗?还是真正的在业务中需要.在现在的开发环境下,什么是竞争力? 举例分页查询来说,每个来公司的程序员都有一套自己写分页的流程,但是这套流程基本上都是重复的,那么…

Docker学习笔记(一)概念理解

一、什么是docker容器 Docker容器是一种轻量级、可移植的软件封装技术,它允许开发者将应用程序及其依赖、配置文件、运行环境等打包到一个独立的、自包含的执行单元中。容器与虚拟机相似,都提供了隔离的运行环境,但容器更加轻量级&#xff0c…

如何清理电脑内存?让电脑运行如飞!

电脑内存(RAM)的清理对于维持系统的流畅运行至关重要。随着使用时间的增加,系统内存会被各种应用程序和后台进程占用,导致系统响应变慢,甚至出现卡顿现象。通过有效地清理内存,可以提升电脑的性能&#xff…

深入理解如何撤销 Git 中不想提交的文件

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

初识 ANTLR4:构建强大解析器的利器

初识 ANTLR4:构建强大解析器的利器 在现代软件开发中,解析和处理各种形式的文本数据是一个常见而又复杂的任务。无论是编译器、数据格式转换工具,还是协议解析器,解析器的作用都至关重要。ANTLR4(ANother Tool for La…