C++中的表达式

news2025/1/11 1:02:47

文章目录

  • 算数操作符
  • 位操作符
    • bitset对象或整型值的使用
    • 将位移操作符用作IO
  • 赋值操作符
    • 赋值操作符的右结合性
    • 赋值操作具有低优先级
  • 自增和自减操作符
  • 条件操作符
  • sizeof操作符
  • 优先级
  • new和delete表达式
  • 类型转换
    • 何时发生隐式转换
    • 显示转换
    • 旧式强制类型转换

C++中的表达式由一个或多个操作数通过操作符组合而成。最简单的表达式仅包含一个字面值常量或变量。每个表达式都会产生一个结果。如果表达式中没有操作符,则其计算结果就是操作数本身。除了特殊的用法外,表达式的结果是 右值,可以读取该结果值,但是不允许对它进行赋值。

算数操作符

在这里插入图片描述
一元操作符优先级最高,其次时乘除,最后是加减。其中求模操作中值得注意得是:

-21 % -8; //-5,当两个数都是负数,求模(取余)操作的为负数或0
21 % -5; //1或-4,当两个操作数只有一个负数时,结果值得符号可依据分母或分子得符号而定,这两种操作得结果取决于机器

在这里插入图片描述

expr1 && expr2;
expr3 || expr4;

逻辑与和逻辑或总是先计算左操作数,只有在左操作数无法确定逻辑表达式得结果时,才会计算右操作数。这种求值策略被称为“短路求值”。

位操作符

在这里插入图片描述
位操作符操作的整数类型可以是有符号的也可以是无符号的。如果操作数为负数,则位操作符如何处理操作数的符号位依赖于机器。由于系统不能确保如何处理操作数的符号位,所以建议使用unsigned整型操作数。

bitset对象或整型值的使用

bitset<30> bitset_quizl;
unsigned long int_quizl = 0;

//操作第27位
bitset_quizl.set(27); // set置为1,reset置为0
int_quizl |= 1UL << 27; // 置1
int_quizl &= ~(1UL << 27); // 置0

一般而言,标准库提供的bitset操作更加直接、更容易阅读和书写、正确的使用的可能性更高。而且bitset对象的大小不受unsigned的位数限制。

将位移操作符用作IO

输入输出标准库分别重载了位操作符>>和<<用于输入和输出。重载的操作符和内置版本有相同的优先级和结合性。优先级比算数操作符低,但比关系操作符、赋值操作符和条件操作符高。

cout << 42 + 10;
cout << (10 < 42);
cout << 10 < 42; // ❌

赋值操作符

赋值操作符的右结合性

int ival, jval; 
ival = jval = 0;

值得注意的是,操作对象必须具有相同的类型,或者具有可转换位同一类型的数据类型。

赋值操作具有低优先级

int i = get_value();
while(i != 42)
{
	// do something();
	i = get_value();
}
// 更简洁的写法
while((i = get_value()) != 42)
{
	// do something;
}

第二种写法更加简洁和清晰。值得注意的是在赋值操作中的圆括号是必须的,因为赋值操作符的优先级低于不等操作符。

自增和自减操作符

  • 后置操作符返回未加1的值
int i = 0, j;
j = ++i; // i = 1, j = 2;
j = i++; // i = 2, j = 1;

前置操作返回自增之后的结果,后置操作返回自增之前的结果。只有在必要时才使用后置操作。因为其在实现的过程中回产生一个临时对象,从而增加时间开销。

  • 在单个表达式中组合使用解引用和自增操作
vector<int>::iterator iter = ivec.begin();
while(iter != ivec.end())
{
	cout << *iter++ << endl;
}

自增操作的优先级高于解引用,因此先自增,在解引用。后置自增返回自增之前的值,因此解引用可以从0开始。

条件操作符

  • 嵌套条件操作符
int i = 10, j = 20, k = 40;
int max = i > j? i > k? i : k
		: j > k? j : k;
  • 在输出表达式中使用条件操作符
cout << (i < j ? i : j);
cout << i < j ? i : j; // ❌

条件表达式的优先级很低,想要不出错,最好用圆括号把表达式括起来。

sizeof操作符

sizeof表达式的结果是编译时常量,通常有以下三种语法形式:

  • sizeof(type name);
  • sizeof(expr);
  • sizeof expr;
// 以下三种得到都是Sales_item的大小
Sales_item item, *p;
sizeof(Sales_item);
sizeof item;
sizeof *p; 

优先级

在这里插入图片描述
在这里插入图片描述
上表按照优先级顺序列出了C++的全部操作符。该表不同优先级的操作符划分到不同段中,每段内各个操作符优先级相同,且都高于后面各段中的操作符。值得注意的后自增操作优先级比前自增操作的优先级更高

new和delete表达式

  • 初始化
\\ 动态创建类类型,回自动调用默认构造函数
string *s = new string;
\\ 内置类型,不会自动初始化
int *pi = new int;
\\ 可通过在类型名后加(),进行值初始化
int *pi = new int();
  • new分配内存失败
    分配失败系统将抛出名为bad_alloc的异常。
  • 在delete之后,重设指针的值
delete p;
p = nullptr;

在delete动态分配的之后,p变成没有意义。在很多机器之上,尽管p没有意义,但仍存放了它之前所指向地址的值,然后p所指向的内存已经被释放,因此p不在有效。
删除指针之后,该指针变成垂悬指针。为了防止出错,在删除指针之后,立即将其置为0。

类型转换

由编译器自动进行类型转换称之为隐式类型转换。

何时发生隐式转换

在下列情况下,将发生隐式类型转换:

  • 混合类型的表达式中,其操作数转化为相同的类型
int ival;
double dval;
ival >= dval; // ival转化为double,一般向精度更大的类型进行转换
  • 用作条件表达式被转换为bool类型
int ival;
if(ival)
while()
&&, ||, !, ?:等等
  • 用一表达式初始化或赋值某个变量,该表达式结果转化为该变量类型。

显示转换

显示转换也称为强制类型转换(cast),包括static_cast、dynamic_cast、const_cast和reinterpret_cast。

  • 何时需要强制类型转换
double dval;
int ival;
ival *= dval; // ival * dval,ival先转double,ival = ival * dval,赋值操作结果转int
ival *= static_cast<int>(dval); // 有效减少隐式转换的次数
  • 使用场景
// dynamic_cast,支持运行时识别指针或引用所指向的对象
// const_cast,添加移除const属性,const_cast<new_type>(expression)
// static_cast,编译器隐式转换的任何类型都可以由static_cast显示完成
// reinterpret_cast,通常为操作数的位模式提供低层次的重新编译。本质上依赖于机器。
//为了安全的使用,要求程序员完全理解所设计的类型,以及编译器实现强制类型转换的细节。
// 转换后的类型通常与原类型完全不相关,用于底层操作,转换为完全不相关的类型,如指针与整数之间的转换。
//这种转换是危险的,可能会导致未定义行为,特别是在内存布局不一致的情况下
int *ip;
char *pc = reinterpret_cast<char*>(ip); // 程序员必须永远记着pc所指向的真实对象是int型,而非字符数组。任何假设pc是字符指针的应用,可能带来未知的错误。

旧式强制类型转换

在引入相知类型转换操作符之前,显示强制类型转换用圆括号实现。

// 以下两种写法都可
char *pc = (char*) ip;
char *pc = char*(ip);

旧式强制类型转换具有和static_cast、const_cast以及reinterpret_cast一样的行为。在合法使用前两者的场景中,提供了与各自对应命名强制转换一样的功能。如果这两种转换均不合法,则执行reinterpret_cast的功能。
支持旧式强制类型转换是为了对保持老程序的兼容性,一般建议使用命名强制转换。

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

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

相关文章

WebSocket 测试入门篇

Websocket 是一种用于 H5 浏览器的实时通讯协议&#xff0c;可以做到数据的实时推送&#xff0c;可适用于广泛的工作环境&#xff0c;例如客服系统、物联网数据传输系统&#xff0c; 基础介绍 我们平常接触最多的是 http 协议的接口&#xff0c;http 协议是请求与响应的模式&…

海外招聘丨 弗拉瑞克商学院—博士研究员:智能家居技术业务和能源管理中的数据分析和人工智能

雇主简介 Vlerick 是一所领先的国际商学院……与众不同。是的&#xff0c;我们提供完全认可的世界一流教育课程&#xff0c;将理论知识和实践见解完美结合。是的&#xff0c;我们是一家领先的学术机构&#xff0c;拥有创新和独立研究的悠久传统。是的&#xff0c;我们拥有国际…

NUTTX移植到STM32

STM32移植NUTTX 1. Ubuntu下搭建开发环境1.1 先决条件1.2 下载 NuttX1.3 使用Make 进行编译1.4 烧录运行 2.通过NUTTX点亮LED2.1 部署操作系统2.2 修改配置文件2.3 编译运行程序 开发板&#xff1a;DshanMCUF407 官方开发文档&#xff1a;安装 — NuttX latest 文档 参考文档&…

Redis 优化秒杀(异步秒杀)

目录 为什么需要异步秒杀 异步优化的核心逻辑是什么&#xff1f; 阻塞队列的特点是什么&#xff1f; Lua脚本在这里的作用是什么&#xff1f; 异步调用创建订单的具体逻辑是什么&#xff1f; 为什么要用代理对象proxy调用createVoucherOrder方法&#xff1f; 对于代码的详细…

Python 中的错误处理与调试技巧

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

关于腾讯4K算法搭建使用

准备国内服务器一台&#xff0c;轻量服务器请尽量开全端口安装linux,centos7.6-7.9系统&#xff0c;记住纯净系统&#xff0c;然后安装宝塔宝塔安装环境为nginx1.24,7.2(PHP版本没有要求)&#xff0c;Mysql5.7(没有要求) 准备活动完毕&#xff01;&#xff01;&#xff01; 上传…

工艺参数优化、工程设计优化!GRNN神经网络+NSGAII多目标优化算法(Matlab)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.GRNN神经网络NSGAII多目标优化算法&#xff0c;工艺参数优化、工程设计优化&#xff08;Matlab完整源码和数据&#xff09; 多目标优化是指在优化问题中同时考虑多个目标的优化过程。在多目标优化中&#xff0c;通…

【Rust自学】11.6. 控制测试运行:并行和串行(连续执行)测试

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.6.1. 控制测试的运行方式 cargo test和cargo run一样&#xff0c;cargo test也会编译代…

nginx负载均衡-基于端口的负载均衡(一)

注意&#xff1a; (1) 做负载均衡技术至少需要三台服务器&#xff1a;一台独立的负载均衡器&#xff0c;两台web服务器做集群 一、nginx分别代理后端web1 和 web2的三台虚拟主机 1、web1&#xff08;nginx-10.0.0.7&#xff09;配置基于端口的虚拟主机 [rootOldboy extra]# …

DDcGAN_多分辨率图像融合的双鉴别条件生成对抗网络_y译文马佳义

摘要&#xff1a; 在本文中&#xff0c;我们提出了一种新的端到端模型&#xff0c;称为双鉴别条件生成对抗网络&#xff08;DDcGAN&#xff09;&#xff0c;用于融合不同分辨率的红外和可见光图像。我们的方法建立了一个生成器和两个鉴别器之间的对抗博弈。生成器的目的是基于特…

【C++/控制台】2048小游戏

源代码&#xff1a; #include <iostream> #include <windows.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <conio.h> #include <time.h>// #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME)…

【Rust自学】11.5. 在测试中使用Result<T, E>

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.5.1. 测试函数返回值为Result枚举 到目前为止&#xff0c;测试运行失败的原因都是因为触…

最新版IDEA新建web项目--小白也能看懂

引言&#xff1a; 此方法适用于 IntelliJ IDEA 2024.1.4 最新版本。 我最初使用的是 Tomcat 8.0.23 版本&#xff0c;搭配 JDK 17。由于 Tomcat 8.0.23 使用了已经被弃用的 JVM 参数&#xff0c;故将 Tomcat 版本更换为 10.1.1。 如果你使用 JDK 17&#xff0c;建议使用 Tom…

ue5玩家角色添加武器。切换武器位置,手上武器放到背上。演示一下人体插槽和武器的连接。仅仅演示,实际项目不是这么用的

把第一人称资源包导进来 这就是我们枪的骨骼网格体 我们找到这个骨骼 右手添加插槽 取个名字 因为武器上也有动画&#xff0c;所有武器单独写个蓝图类 新建一个蓝图类 BP_Weapon 把枪的蓝图拖到人的静态网格体下&#xff0c;成为一个部分 选中BP_Weapon的父类套接字…

微信小程序防止重复点击事件

直接写在app.wpy里面&#xff0c;全局可以调用 // 防止重复点击事件preventActive(fn) {const self this;if (this.globalData.PageActive) {this.globalData.PageActive false;if (fn) fn();setTimeout(() > {self.globalData.PageActive true;}, 3000); //设置该时间内…

Docker入门之docker基本命令

Docker入门之docker基本命令 官方网站&#xff1a;https://www.docker.com/ 1. 拉取官方镜像并创建容器&#xff08;以redis为例&#xff09; 拉取官方镜像 docker pull redis# 如果不需要添加到自定义网络使用这个命令&#xff0c;如需要&#xff0c;直接看第二步 docker r…

SQL Server中可以通过扩展事件来自动抓取阻塞

在SQL Server中可以通过扩展事件来自动抓取阻塞&#xff0c;以下是详细流程&#xff1a; 开启阻塞跟踪配置&#xff1a; • 执行以下SQL语句来启用相关配置&#xff1a; EXEC sp_configureshow advanced options, 1; RECONFIGURE; EXEC sp_configure blocked process thresh…

【VBA】【EXCEL】将某列内容横向粘贴到指定行

Sub CopyRowToColumn()On Error GoTo ErrorHandler 添加错误处理Application.ScreenUpdating FalseApplication.Calculation xlCalculationManualApplication.EnableEvents False 禁用事件处理Dim lastCol As LongDim lastRow As LongDim i As Long, colCount As LongDim …

基于机器学习的故障诊断(入门向)

一、原始信号的特征提取 1.EMD经验模态分解的作用 信号分析&#xff1a;EMD可以将信号分解为多个IMFs&#xff0c;每个IMF代表信号中的一个特定频率和幅度调制的成分。这使得EMD能够提供对信号的时频特征进行分析的能力&#xff08;特征提取用到的&#xff09;。信号去噪&…

多台PC共用同一套鼠标键盘

当环境中有多个桌面 pc 需要操作的时候&#xff0c;在 多台 pc 之间切换会造成很多的不方便 可以通过远程进行连接&#xff0c;但是有一个更好的方案是让多台机器之间共用同一套键盘鼠标 常用的解决方案 synergy 和 sharemouse&#xff0c;通过移动光标在不同的 pc 间切换 s…