【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

浙公网安备 33010602011771号