C/C++陷阱——临时变量的产生和特性
C/C++陷阱——临时变量的产生和特性
在学习C++常引用时,有这样一段代码引起了我的注意:
int a = 1;
double& b = a;
当我编译这段代码时,竟然报错了:
按理来说,初始化引用时不能涉及权限的放大(如用const int
初始化int&
),但是这里只是权限的平移,为什么会错误呢?
我们可以看到报错信息里有这样一句话:非常量限定
,这指的又是什么呢?
这就是本次要讨论的重点——临时变量的产生和特性:
在C和C++中,临时变量通常指的是临时创建并存储数据的变量,它们在表达式求值或函数调用中起到临时存储值的作用。这些临时变量通常是由编译器自动生成的,无需程序员显式声明或管理。
临时变量的产生
临时变量主要在下面这两种情况下产生:
- 类型转换
当需要将一个数据类型转换为另一个数据类型时,通常会生成临时变量来保存转换后的值
例如:
int a = 10;
double b = a;
我们都知道,将整型变量a
赋值给双精度浮点型变量b
时,涉及到了隐式类型转换,但我们可能大多数都忽略了这个过程中就产生了一个临时变量来存储转换后的值,最后变量b
接收的就是这个临时变量。因为只有这样,我们才能在类型转换的过程中确保变量a
的数据是完整的、合规的、安全的。
又例如:
int a = 1;
int* pt = (int*)a;
我们总不能说,将整型变量a
强制转换为整型指针后,整型变量a
就变成指针了吧。
- 函数调用
当一个函数返回一个值时,通常会生成临时变量来存储函数的返回结果。这个临时变量可以被赋给其他变量或用于进一步的操作。
int Add(int a, int b)
{int sum = a + b;return sum;
}int main()
{int ret = Add(1, 2);return 0;
}
Add
函数就是一个简单的两数相加的函数。那么小伙伴觉得这个函数的返回值是什么?是变量sum
吗?当然不是,应该清楚局部变量出了其所在函数的作用域后就会被销毁,因此当Add
函数被调用完后,sum
所代表的值就是一个随机数了。因此实际上,编译器一般都会生成一个临时变量来存储函数返回的结果,最后ret
接受的也是这个临时变量。
除了上面两种情况外,还有其他的一些情况也会有临时变量的产生,大家了解即可:
- 表达式求值:当需要计算一个表达式,特别是包含多个操作数和操作符的复杂表达式时,编程语言通常会生成临时变量来保存中间结果。
- 中间计算:在执行复杂计算时,可以使用临时变量来存储中间计算结果,以避免重复计算相同的值。
- 循环迭代:在循环结构中,迭代计数器通常被视为临时变量,因为它们在每次迭代中都会被更新。
- 条件语句:在条件语句中,如果需要根据条件执行不同的操作,临时变量可能会用于存储条件的结果或中间值。
- 数组和容器操作:在对数组、向量、列表等数据结构进行操作时,可能会生成临时变量来存储临时元素或中间结果。
- 错误处理:在处理异常或错误时,临时变量可以用于存储错误信息或状态。
临时变量的常性
临时变量有一个很重要的特性:常量性
这一个特性确保了临时变量是不可以被修改,这其中也就包括了权限不能被放大。
例如:
int Add(int a, int b)
{int sum = a + b;return sum;
}int main()
{Add(1, 2)++;return 0;
}
就会报错:
这里解释一下左值和右值的概念:
- 左值(L-value):左值是可以出现在赋值操作符(例如=)的一侧的表达式,表示一个可以被赋值的内存位置,通常是一个变量。左值表示一个标识符或一个引用,它指向内存中的某个位置。例如,如果你有一个变量x,那么x就是一个左值,因为你可以将一个值赋给它,如x = 10。
- 右值(R-value):右值是一个表达式的结果值,它可以出现在赋值操作符的右侧。右值通常是计算的结果,它可以是常数、临时变量或函数的返回值。例如,如果你有一个表达式x + y,它的结果是一个右值,因为它代表一个值,但你不能将一个值赋给它。
报错信息显示,函数的返回值不是一个左值,也就是说返回的临时变量是不可被修改的。这也从侧面反映了临时变量的常性。
除此之外,临时变量还有其他一些特性,大家仅作了解即可:
- 短暂寿命:临时变量通常在其创建点的作用域内存在,一旦超出该作用域,它们就会被销毁。这使它们成为一种短暂的存储设备。
- 匿名:通常,临时变量没有显式的名称,因为它们是在表达式求值或函数调用期间自动创建的。它们只是在内部存储中的值。
- 用于中间计算:临时变量通常用于存储中间计算结果或值的转换。它们帮助管理复杂的表达式,确保正确的计算顺序。
- 可被编译器优化:现代编译器通常会进行优化,以最小化临时变量的使用,以提高性能。它们可以消除不必要的临时变量,以减少内存开销。
- 值语义:临时变量通常采用值语义,这意味着它们存储的是具体的值,而不是引用或指向其他变量。这有助于避免共享状态和副作用。
- 用于函数返回:在函数返回值的情况下,临时变量通常用于存储函数的结果,以便将其传递给调用方。
- 隐式创建和销毁:编程语言和编译器通常会自动创建和销毁临时变量,程序员无需显式管理它们的生命周期。
- 类型与原始值相关:临时变量的类型通常与它们所包含的值的类型相关,以确保类型的一致性。
总结
通过对临时变量的了解,我们就可以解释最开始提到的问题了:
int a = 1;
double& b = a;
当用整形变量a
初始化浮点型引用b
时,涉及到了隐式类型转换,那么中间就会产生一个double
型临时变量来临时存储a
的值,但由于临时变量具有常性,其权限不能被放大,因此double& b = a;
这句就是错误的。我们应该改为**const double& b = a;
确保权限不变**。
本篇完。
相关文章:

C/C++陷阱——临时变量的产生和特性
C/C陷阱——临时变量的产生和特性 在学习C常引用时,有这样一段代码引起了我的注意: int a 1; double& b a;当我编译这段代码时,竟然报错了: 按理来说,初始化引用时不能涉及权限的放大(如用const in…...

【音视频|ALSA】SS528开发板编译Linux内核ALSA驱动、移植alsa-lib、采集与播放usb耳机声音
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
C/C++基础讲解(一百三十一)之经典篇(信息合并/平均分数存储)
C/C++基础讲解(一百三十一)之经典篇(信息合并/平均分数存储) 程序之美 前言 很多时候,特别是刚步入大学的学子们,对于刚刚开展的计算机课程基本上是一团迷雾,想要弄明白其中的奥秘,真的要花费一些功夫,我和大家一样都是这么啃过来的,从不知到知知,懵懂到入门,每一步…...

【ROS】使用vscode浏览navigation2源码时,提示:没有那个文件或目录
【ROS】郭老二博文之:ROS目录 1、问题描述 使用vscode浏览navigation2源码时,头文件下面有波浪线,并提示:没有那个文件或目录。比如没有:geometry_msgs/msg/polygon.h 错误信息: 无法打开源文件 “geometry_msgs/msg/polygon.h” (dependency of “nav2_controller/co…...

ARM-day9作业
main.c: #include "uart.h"#include "key_it.h"int main(){char c;char *s;uart4_init(); //串口初始化//中断初始化key_it_config();key3_it_config();//完成GPIO相关初始化all_led_init();//风扇初始化fs_init();//蜂鸣器初始化fmq_init();while(1){…...

ORA-00600: internal error code, arguments
通过rman将11g异机升级到19c时,应用归档时报错,报错如下 RMAN> recover database ; Starting recover at 2023-10-15 21:10:02 allocated channel: ORA_DISK_1 channel ORA_DISK_1: SID5776 device typeDISK starting media recovery media recove…...
C#里氏替换
在C#中,里氏替换原则是面向对象编程中的一个重要原则,它是关于继承和多态性的概念。 里氏替换原则的定义是:如果S是T的子类型(或者T是S的基类型),那么程序中任意使用T类型的地方都可以替换为S类型而不会产…...

Java-使用sqlSessionTemplate实现批量更新-模拟mybatis 动态sql
环境准备(非核心方法) 创建表 创建表的sql(下表是基于Oracle创建的) CREATE TABLE "SYSTEM"."STUDENT" ("ID" NUMBER(10, 0),"NAME" VARCHAR2(20 BYTE),"ADDRES" CLOB,PRIMARY KEY ( …...

Eslint配置 Must use import to load ES Module(已解决)
最近在配置前端项目时,eslint经常会碰到各种报错(灰常头疼~) Syntax Error Error No ESLint configuration found.Syntax Error: Error: D:\dmq\dmq-ui.eslintrc.js: Environment key “es2021” is unknown at Array.forEach ()error in ./…...

正向代理(流量代理)
文章目录 正向代理与反向代理流量转发工具环境准备reGeorg 正向代理与反向代理 正向代理是客户端和其他所有服务器(重点:所有)的代理者 反向代理是客户端和所要代理的服务器之间的代理。 流量转发工具 需要放在拿到shell的服务器上可使用 …...

易天光通信推出100G BIDI ER光模块最新解决方案
随着数字信息时代的快速发展,网络通信技术的迅猛进步成为推动科技创新和产业升级的重要引擎之一。作为光通信行业的新秀,近期易天光通信推出了全新的100G BIDI ER1 Lite光模块和100G BIDI LR1 Lite光模块,助力崭新的未来网络建设。 易天光通…...

Flask框架配置celery-[1]:flask工厂模式集成使用celery,可在异步任务中使用flask应用上下文,即拿即用,无需更多配置
一、概述 1、celery框架和flask框架在运行时,是在不同的进程中,资源是独占的。 2、celery异步任务如果想使用flask中的功能,如orm,是需要在flask应用上下文管理器中执行orm操作的 3、使用celery是需要使用到中间件的࿰…...

合并二叉树
题目链接 合并二叉树 题目描述 注意点 如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点 解答思路 先序遍历二叉树,将重叠部分节点值相加作为新节点的值&…...

Sanic——Python函数变成API的神器
今天给大家介绍一个超好用的框架,迅速将Python函数变成API,它就是最近越来越火的异步Web框架Sanic。 1. Sanic简介 Sanic 是 Python3.7 Web 服务器和 Web 框架,旨在提高性能。它允许使用 Python3.5 中添加的async/await语法,这使…...

Windows连接不上VMware,ping不通的问题
文章目录 防火墙问题Windows和虚拟机下的ip不一致导致的问题VMware Network Adapter (适配器)丢失的问题参考文档 防火墙问题 防火墙默认不会拦截ping命令,除非你个人设置了Linux防火墙Centos7的常用命令关闭防火墙 systemctl stop firewalld #停止Windows和虚拟机…...
24、Flink 的table api与sql之Catalogs(java api操作数据库、表)-2
Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…...

【MySQL】深入了解索引的底层逻辑结构
文章目录 主键排序一. InnoDB的索引结构1. 单个page2. 多个page 二. 为什么选择B树三. 聚簇索引和非聚簇索引结束语 主键排序 我们创建一个user表,并乱序插入数据 mysql> create table if not exists user(-> id int primary key,-> age int not null,-&…...

Android之SpannableString使用
文章目录 前言一、效果图二、实现代码总结 前言 在开发中,往往有些需求是我们不愿意遇到的,但是也不得不处理的事情,比如一段文案,需要文案中某些文字变颜色或者点击跳转,所以简单写了几句代码实现,没什么…...
【Python】Python求均值、中值和众数
Python求均值、中值和众数 我们将讨论如何使用描述性统计数据进行数据分析,包括: 均值——一组值的平均值; 中值——当所有值按顺序排列时的中间值; 众数——最常出现的值。 以上这些都是集中趋势度量,每种都会产生一个值来表示一组值中的“…...

NPM 常用命令(十二)
目录 1、npm unpublish 1.1 使用语法 1.2 描述 2、npm unstar 2.1 使用语法 3、npm update 3.1 使用语法 3.2 描述 3.3 示例 插入符号依赖 波浪号依赖 低于 1.0.0 的插入符号依赖 子依赖 更新全局安装的包 4、npm version 4.1 使用语法 5、npm view 5.1 使用语…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...