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

深蓝学院C++基础与深度解析笔记 第 4 章 表达式

第 4 章 表达式

一、表达式基础

A、表达式: 由一到多个操作数组成,可以求值并 ( 通常会 ) 返回求值结果:

#include <iostream>
int main(){int x;x = 3;
}
  • 最基本的表达式:变量、字面值
  • 通常来说,表达式会包含操作符(运算符), 且可以嵌套
  • 操作符的特性
    ● 接收几个操作数:一元、二元、三元 ?:
    ● 操作数的类型 - 类型转换
    ● 操作数是左值还是右值
    ● 结果的类型
    ● 结果是左值还是右值
    ● 优先级与结合性 (cpp-reference) ,可以通过小括号来改变运算顺序,和数学上一样,相同的优先级的结合性相同
    ● 操作符的重载 不改变接收操作数的个数、优先级与结合性
  • 操作数求值顺序的不确定性

最终的顺序:

括号 -> 优先级 -> 结合性

PS: 函数调用也是表达式:

#include<iostream>
void fun(int p12, int p2)
{std::cout<< p1 << ' ' << p2 << '\n';
}
int main(){int x=0;fun(x=x+1,x=x+1); 
}

函数参数计算顺序可能不同

B、左值和右值
传统的左值与右值划分

– 来源于 C 语言:左值可能放在等号左边;右值只能放在等号右边
– 在 C++ 中,左值也不一定能放在等号左边;右值也可能放在等号左边

● 所有的划分都是针对表达式的,不是针对对象或数值,针对表达式结果
– glvalue :泛左值:标识一个对象、位或函数
– prvalue :纯右值:用于初始化对象或作为操作数
– xvalue : 将亡值:表示其资源可以被重新使用,在内存销毁前把内容保留下来

decltype(实体/表达式)
在这里插入图片描述
● 左值与右值的转换
– 左值转换为右值( lvalue to rvalue conversion )
– 临时具体化( Temporary Materialization )
● 再论 decltype
– prvalue → type
– lvalue → type&
– xvalue → type&&

std::move()可以构造亡值

C、类型转换
一些操作符要求其操作数具有特定的类型,或者具有相同的类型,此时可能产生类型转换
1、 隐式类型转换

– 自动发生
– 实际上是一个(有限长度的)转型序列
– https://en.cppreference.com/w/cpp/language/implicit_conversion
– 并非所有类型之间都可以任意转换
数值提升:精度、内存空间提升;数值之间的转换可以导致精度缺失,更改值

2、显示类型转换
使用的时候小心谨慎些,容易出错,风险较大;尽量写长些,容易识别

– 显式引入的转换  可以使用括号和类型结合转换
– static_castconst_castdynamic_castreinterpret_cast
– C 形式的类型转换

关于类型转换的补充:

静态转换(Static Cast):
静态转换是最常用的类型转换方式之一,用于显式转换一种类型为另一种类型,但在转换时没有进行运行时检查。静态转换可以用于类层次结构中的上下转换(派生类向基类转换),以及非相关类型之间的转换。使用静态转换时,需要注意类型转换的安全性,因为它没有运行时检查。示例:

int x = 10;
double y = static_cast<double>(x);  // 将整数转换为浮点数

动态转换(Dynamic Cast):
动态转换用于在类层次结构中进行安全的上下转换(派生类向基类转换),并提供运行时类型检查。如果转换无效,即源指针指向的对象不是目标类型的一个有效派生类对象,动态转换将返回空指针(对于指针类型)或引发 std::bad_cast 异常(对于引用类型)。示例:

Base* basePtr = new Derived();  // 派生类指针赋值给基类指针
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);  // 动态转换
if (derivedPtr != nullptr) {// 转换成功,可以安全使用 derivedPtrderivedPtr->doSomething();
}

重新解释转换(Reinterpret Cast):
重新解释转换是一种较为低级别的转换方式,用于将一个指针或引用转换为不同类型的指针或引用,甚至可以将整数类型转换为指针类型或反之。它的行为比较危险,需要谨慎使用,因为它不会进行任何类型检查和转换。示例:

int x = 10;
double* ptr = reinterpret_cast<double*>(&x);  // 将整数指针转换为双精度浮点数指针

常量转换(Const Cast):
常量转换用于移除表达式的常量性(const)或将常量性添加到表达式。它主要用于处理函数重载或操作函数返回类型为常量的情况。常量转换不能用于修改实际的常量对象。示例:

const int x = 10;
int* ptr = const_cast<int*>(&x);  // 移除常量性以获取非常量指针
*ptr = 20;  // 修改通过常量指针获取的值

使用Boost将数字型对象的值转换为字符文本格式:boost::lexical_cast

在进行类型转换时,应谨慎考虑类型安全性和潜在的运行时错误

二、表达式详述

A、算术操作符
● 共分为三个优先级
– + , - (一元,正负号),可以让数组变成指针,类型提升
– * , / , % (%只接受整数)
– + , - (二元,加减号)
● 均为左结合的
● 通常来说,操作数与结果均为算数类型的右值;但加减法与一元 + 可接收指针
● 一元 + 操作符会产生 integral promotion
● 整数相除会产生整数,向 0 取整
● 求余只能接收整数类型操作数,结果符号与第一个操作数相同
● 满足 (m / n) * n + m % n == m

B、逻辑与关系操作符
● 关系操作符接收算术或指针类型操作数;逻辑操作符接收可转换为 bool 值的操作数
● 操作数与结果均为右值(结果类型为 bool )
● 除逻辑非外,其它操作符都是左结合的
● 逻辑与、逻辑或具有短路特性
● 逻辑与的优先级高于逻辑或,建议使用括号!
● 通常来说,不能将多个关系操作符串连 例子:c>b>a ×
● 不要写出 val == true 这样的代码
● Spaceship operator: <=>用于比较复杂的对象的对比(C++20)
– strong_ordering
– weak_ordering
– partial_ordering nan:not a number 非正常数字

c、位操作符
~:按位取反
在这里插入图片描述
在这里插入图片描述

接收右值,进行位运算,返回右值
● 除取反外,其它运算符均为左结合的
● 注意计算过程中可能会涉及到整形提升 integral promotion
● 注意这里** **
● 移位操作在一定情况下等价于乘(移位 :左移<< 1(乘2的1次)、右移>>1(除2)) 2 的幂,但速度更快
<<n : 乘2的n次 >>n : 除2的n次
● 注意整数的符号与位操作符的相关影响
– integral promotion 会根据整数的符号影响其结果
– 右移保持符号,但左移不能保证

D、赋值操作符
● 左操作数为可修改左值;右操作数为右值,可以转换为左操作数的类型
● 赋值操作符是右结合的:先处理右侧的
● 求值结果为左操作数
● 可以引入大括号(初始化列表)以防止收缩转换( narrowing conversion )
● 小心区分 = 与 ==
● 复合赋值运算符
交换x,y:
在这里插入图片描述

E、自增与自减运算符
● ++; –
● 分前缀与后缀两种情况

  • 操作数为左值;前缀时返回左值操作完之后的;后缀时返回操作之前的右值

● 建议使用前缀形式

F、其它操作符
● 成员访问操作符: . 与 ->
– -> 等价于 (*).
– . 的左操作数是左值(或右值),返回左值(或右值 xvalue ),和返回类型相同
– -> 的左操作数指针,返回左值
● 条件操作符
– 唯一的三元操作符: ?:,可以嵌套
在这里插入图片描述

– 接收一个可转换为 bool 的表达式与两个类型相同的表达式,只有一个表达式会被求值
– 如果表达式均是左值,那么就返回左值,否则返回右值
– 右结合,嵌套多层的?:会先转换成 单个的 ?:

G:其他操作符:
逗号操作符
– 确保操作数会被从左向右求值
– 求值结果为右操作数
– 左结合
●sizeof 操作符
– 操作数可以是一个类型(需要加括号)或一个表达式
并不会实际求值,而是返回相应的字节尺寸
● 其它操作符
– 域解析操作符 ::
– 函数调用操作符 ()
– 索引操作符 []
– 抛出异常操作符 throw
– …

在 C++17 中,可以确保 e1 会先于 e2 被求值
– e1[e2]
– e1.e2
– e1.e2
– e1→
e2
– e1<<e2
– e1>>e2
– e2 = e1 / e2 += e1 / e2 *= e1… (赋值及赋值相关的复合运算)
● new Type(e) 会确保 e 会在分配内存之后求值

相关文章:

深蓝学院C++基础与深度解析笔记 第 4 章 表达式

第 4 章 表达式 一、表达式基础 A、表达式: 由一到多个操作数组成&#xff0c;可以求值并 ( 通常会 ) 返回求值结果: #include <iostream> int main(){int x;x 3; }最基本的表达式&#xff1a;变量、字面值通常来说&#xff0c;表达式会包含操作符&#xff08;运算符…...

CLION开发STM32之W5500系列(一)

开篇说明 本系列适用于需要使单片机通过网口进行通信的开发。针对的是刚入门的同学们,也是个人的经验分享。本次使用到的芯片为stm32f103vet6(其他的也可以)本次使用的网口模块为W5500,其网关有示例程序均可以参考.本次使用Clion+OpenOCD+ARM-GCC 进行开发、烧录、编译.建议熟…...

Web3通过ganache运行起一个本地虚拟区块链

通过文章 Web3开发准备工作 手把手带你创建自己的 MetaMask 账号大家简单的对网络 有了个比较模糊的概念 不同的网络连接这不同的区块链 那么 我们就要搞清楚 我们切换不同的网络 我们的数字资产是不一样的 在这里 我们需要先安装一个插件工具 ganache 我们先在本地创建一个文…...

01 背包问题解析与代码 python 实现

01 背包问题解析与代码 问题定义 给定一堆具有不同重量 { w 1 , w 2 , ⋯ , w n } \{ w_1,w_2, \cdots,w_n \} {w1​,w2​,⋯,wn​}与价值 { v 1 , v 2 , ⋯ , v n } \{ v_1,v_2, \cdots,v_n \} {v1​,v2​,⋯,vn​}的背包&#xff08;knapsack&#xff09;&#xff0c;在总重…...

Vue实现前端视频展示列表及特征提取、笔记、删除、文件夹组织功能

Vue实现前端视频展示列表及特征提取、笔记、删除、文件夹组织功能 在前端展示上传的视频列表时&#xff0c;我们可以使用Element-UI中的Card组件来实现。同时&#xff0c;我们还可以添加一些功能&#xff0c;如缓存播放的视频、选择视频文本特征提取处理、写笔记、删除视频、组…...

多传感器时频信号处理:多通道非平稳数据的分析工具(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

数据结构算法 -分而治之算法

引言 坤坤是一个养鸡场的员工&#xff0c;他非常热爱他的工作&#xff0c;并且总是努力提高他的专业技能。有一天&#xff0c;养鸡场接到了一项任务&#xff1a;在短时间内处理一批大量的鸡。 这批鸡数量非常大&#xff0c;比普通的数量要多得多&#xff0c;坤坤意识到他们需…...

涉密信息系统口令管理制度

第一条 口令是涉密信息系统身份认证的基本防护措施&#xff0c;为保障 涉密信息系统的安全运行&#xff0c;规范网络用户及系统口令&#xff0c;特制定本制度。 第二条 具有口令功能的计算机、网络设备等计算机信息系统设 备&#xff0c;必须使用口令对用户的身份进行验证…...

UML与流程图

UML简介 UML&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;是一种用于软件系统分析与设计的标准化建模语言。它提供了一套丰富的图形符号和规则&#xff0c;可用于描述系统的结构、行为和交互&#xff0c;帮助开发人员、设计师和利益相关者之间进…...

音视频开发Level0: 入门级20~25k的工作

今天给大家分享一个音视频开发领域&#xff0c;入门级别的工作&#xff0c;要求不高。 主要做什么呢&#xff0c;行车记录仪&#xff0c;运动相机&#xff0c;各种拍摄器材包括医疗领域的喉镜啊&#xff0c;等等。 这种产品&#xff0c;招人的公司深圳最多&#xff0c;因为深…...

Git第一章、Git的原理与使用

目录 一、Git安装 1.1Linux Centos安装 二、Git基本操作 2.1创建 Git 本地仓库 2.2配置Git 三、认识工作区、暂存区、版本库 3.1添加文件&#xff08;场景一&#xff09; 3.2修改文件 3.3版本回退 四、撤销修改 4.1情况一&#xff1a;对于工作区的代码&#xff0c;还…...

软件开发流程

目录 软件软件开发流程的演变 瀑布模型敏捷模型 XPSCRUMDevOps 1.软件 与计算机系统操作有关的计算机程序、可能有的文件、文档及数据。 软件可以分为两种主要类型&#xff1a; 独立软件&#xff1a;独立软件是一种完整的应用程序&#xff0c;可以直接在计算机或移动设备上…...

编程语言的优劣评选标准与未来发展趋势——探索最佳编程语言选择

编程语言的优劣评选标准与未来发展趋势——探索最佳编程语言选择 评判标准不同编程语言的优点与缺点分析对编程语言未来发展的猜测和未来趋势 &#x1f495; &#x1f495; &#x1f495; 博主个人主页&#xff1a; 汴京城下君–野生程序员&#x1f495; &#x1f495; &#x…...

axios 发送请求请求头信息不包含Cookie信息

问题 axios 发送请求请求头信息不包含Cookie信息 详细问题 使用VueSpringBoot进行项目开发&#xff0c;axios进行网络请求&#xff0c;发送请求&#xff0c;请求头信息不包含Cookie信息 具体如下 实际效果 预期效果 解决方案 作用域 Vue项目全局配置 打开Vue项目的入口…...

正则表达式笔记

/你的正则表达式写在这里/ 1? 1出现0次或1次 1* 1出现0次或多次 1 1出现1次或多次 1{2} 1出现了2次 1{2,3} 1出现了2到3次 1{2,} 1出现了2次及以上 (5555){1} 5555出现了1次 (dog|cat) dog或者cat [a-zA-Z] a…...

数据结构链表(C语言实现)

绪论 机遇对于有准备的头脑有特别的亲和力。本章将讲写到链表其中主要将写到单链表和带头双向循环链表的如何实现。 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看&#xff09;。 附&#xff1a;红色&#xff0c;部分为重点部分&#xff1b;蓝颜色为需要记忆的…...

Springboot实现接口传输加解密

前言 先给大家看下效果&#xff0c;原本我们的请求是这样子的 加密后的数据传输是这样子的 加解密步骤&#xff1a; 1.前端请求前进行加密&#xff0c;然后发送到后端 2.后端收到请求后解密 3.后端返回数据前进行加密 4.前端拿到加密串后&#xff0c;解密数据 加解密算法&…...

TypeScript类型系统:强类型的优势和使用方式

目录 引言强类型的优势更好的代码可读性更好的代码可维护性更好的代码重构能力更好的代码可靠性更好的代码重用能力 使用方式声明变量类型函数参数和返回值类型类型别名泛型类型&#xff08;了解&#xff09; 总结 引言 在上一篇文章《TypeScript入门指南&#xff1a;从JS到TS的…...

有没有可以代替风铃系统的专业问卷工具?

风铃系统问卷是一种流行的调查和数据分析工具&#xff0c;已广泛应用于学术研究、市场营销和社会科学。然而&#xff0c;有几种替代产品提供了与风铃系统类似的特性和功能&#xff0c;可以被企业用来进行调查和分析数据。在这篇文章中&#xff0c;我们将介绍风铃系统的十大替代…...

【数字调制】数字调制技术FSK与PSK分析与研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...