【C++】7.表达式[深蓝学院C++第5章]

前言

 

一.表达式基础

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

1.1引入

最基本的表达式:变量、字面值

表达式一般会包含操作符(运算符)

操作符的特性:

(1)接收几个操作数

(2)操作数的类型——类型转换,如整型+浮点型

(3)操作数是左值还是右值

(4)结果的类型

(5)优先级与结合性,可以通过小括号来改变运算顺序

(6)操作符的重载——用在类上,不改变接收操作数的个数、优先级与结合性

操作数求值顺序的不确定性,如fun(x=x+1,x=x+1);

1.2左值和右值

参考资料:https://zhuanlan.zhihu.com/p/526034602

 

在 c 中,左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式). 

C++标准委员会把所有表达式分为两种类型:泛左值glvalue和右值rvalue

泛左值可以分为左值lvalue和将亡值xvalue

右值可以分为纯右值prvalue和将亡值xvalue

左值lvalue:可以取地址的值,或者说是具有名称的值

纯右值prvalue:不能取地址的值,或者说是没有名称的值。包括字面值、算数表达式、lambda表达式、栈上的匿名对象、后置自增和自减表达式、函数返回值

将亡值xvalue是即将销毁的值

1.3左值、右值和引用

T&,左值引用;T&&,右值引用;都必须在声明时初始化。

左值引用是地址,右值引用也是地址,都必须在声明时初始化。

1.4左右值引入的类型转换

常用的类型转换有dynamic_cast、static_cast、reinterpret_cast、const_cast,

引入左右值引用之后多了两个类型转换的方式:std::move和std::forward(暂略),

std::move是C++11引入的移动构造函数,默认移动构造函数会执行浅拷贝操作,与拷贝构造函数不同的是,前者会在拷贝结束后把源对象内的指针置空。

因此,所谓移动,就是指将其他对象在堆上拥有的内存资源“移为己用”。

 

1.5算术运算符

共分为三个优先级:

(1)+、-,代表正负

(2)*、/、%,乘除取余

(3)+、-,二元加减

均为左结合

一元+操作符会产生取整效果,short x=0;auto y=+x; y的类型是int

整数相除会产生整数、向0取整

取余只能接受整数类型操作数,结果的符号与第一个操作数相同

满足(m/n)*n+m%n==m

1.6逻辑与关系操作符

关系操作符接收算数或指针类型的操作数,如大于小于等;逻辑操作符接收可转换为bool值的操作数;

操作数与结果均为右值,类型为bool;

除逻辑非外,其他操作符都是左结合的;

逻辑与、逻辑或具有短路特性;

逻辑与的优先级高于逻辑或;

一般不能讲关系操作符串联;

不要写val==true这种代码;int a = 3,a==true?等价于 a == 1?,结果是不成立

C++20引入的操作符spaceship operator <=>:

auto res = (a <=> b);

res>0 说明a>b,

res<0说明a<b

res==0说明a==b

spaceship operator产生的结果:

(1)std::strong_ordering是三路比较的结果类型,分别为greater、less、equal、等价,隐含可替换性、即可以替换大小比较;

(2)std::weak_ordering是三路比较的结果类型,没有equal,只是等价,不完全相同,如长宽不同但面积相同的情况;

(3)partial_ordering,当存在一些不可比较的情况时,如和NaN比较时,结果可能是std::partial_ordering::unordered

 1.7位操作符

~按位取反

&按位与

|按位或

^按位异或

1.接收右值,进行位运算,返回右值

2.除取反外,其他运算符均为左结合

3.注意计算过程中可能会涉及到的intergal promotion,如对char取反时会进行static_cast<int>转换

4.注意没有短路逻辑

5.移位操作在一定情况下等价于乘/除2,但速度更快

6.注意整数的符号位与位操作符的相关影响

(1)intergral promotion会根据整数的符号影响其结果

(2)右移保持符号,但左移不能保证

 1.8赋值操作符

左操作数为可修改左值;右操作数为右值,可以转换为左操作数的类型,

赋值操作符是右结合的,x=y=3,这样写是合理的,从右往左算,

求值结果为左操作数,(x=5)=2;这样写也是可以的,

可以引入大括号(初始化列表)以防止收缩转换( narrowing conversion ),如short x = 0x8000 0001;后x=1;而加大括号后会编译报错

小心区分 = 与 ==

复合赋值运算符,*=  /=  +=  -=等等

 1.9自增自减运算符

 ++; --

分前缀与后缀两种情况,取值前运算还是取值后运算

操作数为左值;前缀时返回左值,因为需要返回历史值;后缀时返回右值,因为此时可以返回最新值

建议使用前缀形式

 1.10其他操作符

 成员访问操作符,.与->

(1).的左操作数是对象

(2)->的左操作数是指针,等价于(*ptr).

条件操作符?:

(1)唯一的三元操作符

(2)接收一个可转换为bool的表达式与两个类型相同的表达式,只有一个表达式会被求值

(3)如果表达式均是左值,那么就返回左值,否则返回右值

(4)右结合

逗号操作符

(1)确保操作数会被从左到右求值

(2)求值结果为右操作数

(3)左结合

sizeof操作符

(1)操作数可以是一个类型或一个表达式

(2)并不会实际求值,而是返回相应的尺寸

其他操作符:

(1)域解析运算符::

(2)函数调用操作符()

(3)索引操作符[]

(4)抛出异常操作符 throw

posted @ 2023-02-24 19:26  啊原来是这样呀  阅读(51)  评论(0)    收藏  举报