第四章 表达式
表达式由一个或多个运算对象组成,对表达式求值将得到一个结果。字面值和变量时最简单的表达式,其结果就是字面值和变量的值。把一个运算符和一个或多个运算对象结合起来可以生成复杂的表达式。
4.1 基础
4.1.1 基本概念
- 组合运算符和运算对象
对于含有多个运算符的复杂表达式来说,要想理解他的含义首相要理解运算符的优先级、结合律以及运算对象的求值顺序。 - 运算对象转换
运算对象常常由一个类型转换成另外一种类型。 - 重载运算符
对已经存在的运算符赋予自定义的意义 - 左值和右值
4.1.2 优先级与结合律
- 括号无视优先级与结合律
- 优先级与结合律有何影响
结合律对表达式产生影响的一个典型示例是输入输出运算。
4.1.3 求值顺序
这部分需要参考加减乘除等运算的先后顺序,在此不做说明。
4.2 运算符
- 算术运算符
4.3 逻辑和关系运算符
- 逻辑与和逻辑或运算符
- 逻辑与 :当且仅当两个运算对象都为真时结果为真
- 逻辑或 :只要两个运算对象中的一个为真结果就为真
短路求值:
- 对于逻辑与运算符来说,当且仅当左侧运算对象为真时才对右侧运算对象求值。
- 对于逻辑或运算符来说,当且仅当左侧运算对象为假时才对右侧运算对象求值。
- 逻辑非运算符
逻辑非(!)运算符 将运算对象的值取反后返回。 - 关系运算符
4.4 赋值运算符
- 赋值运算满足右结合律
int iVal,jVal;
iVal=jVal=0;
- 赋值运算优先级较低
- 切勿混淆相等运算符和赋值运算符
if(i=j) //赋值运算符
if(i==j) //相等运算符
// 用相等运算符时 建议把数值写在等式左边
- 复合赋值运算符
4.5 递增和递减运算符
++i :先增加再使用
i++: 先使用后增加
4.6 成员访问运算符
obj.mem: 对象的实例访问成员用点运算符
pObj->mem: 对象实例的指针访问成员用->
4.7 条件运算符
cond ? expr1 : expr2;
4.8 位运算符
- 移位运算符
<<:左移; <<:右移
左移运算符<< 在右侧插入值为0的二进制位。
右移运算符>> 的行为则依赖于左侧运算对象的类型:
- 如果该运算对象为无符号类型,在左侧插入值为0的二进制位
- 如果该运算对象是带符号类型,在左侧插入符号位的副本或值为0的二进制位,如果选择要视环境而定
- 位求反运算符
位求反运算符(~) 将运算符对象逐位求反后生成一个新值,将1置为0、将0置为1 - 位与、位或、位异或运算符
4.9 sizeof运算符
sizeof运算符返回一条表达式或一个类型名字所占的字节数。
#include <iostream>
using namespace std;
struct Sales_data
{
int bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
int main()
{
Sales_data data, *p;
cout << "Sales_data sizeof:" << sizeof(Sales_data) << endl;
cout << "data sizeof:" << sizeof data << endl;
cout << "p sizeof:" << sizeof p << endl;
cout << "*p sizeof:" << sizeof *p << endl;
cout << "data.revenue sizeof:" << sizeof data.revenue << endl;
return 0;
}
结果:
Sales_data sizeof:16
data sizeof:16
p sizeof:4
*p sizeof:16
data.revenue sizeof:8
个类型具体占用几个字节是与环境有关的,不同的机器显示会有出入,不用纠结。
4.10 逗号运算符
逗号运算符:含有两个运算对象,按照从左向右的顺序依次求值。
对于逗号运算符来说:
- 首先对左侧的表达式求值,然后将求值结果丢弃掉。逗号运算符真正的结果是右侧表达式的值。
- 如果右侧运算对象是左值,那么最终的求值结果也是左值。
4.11 类型转换
4.11.1 算术转换
算术转换:把一种算术类型转换成另外一种算术类型。算术转换的规则定义了一套类型转换的层次,其中运算符的运算对象将转换成最宽的类型。
- 整型提升
负责把小整数类型转换成较大的整数类型。 - 无符号类型的运算对象
- 若果一个运算对象是无符号类型、另外一个运算对象是带符号类型,而且其中的无符号类型不小于带符号类型,那么带符号的运算对象转换成无符号的。
- 如果带符号类型大于无符号类型,此时转换的结果依赖于机器。
4.11.2 其他隐式类型转换
- 数组转换成指针
- 转换成bool类型
- 转换成常量
- 等等
4.11.3 显示转换
就是运用函数进行转换
- static_cast
只要不包含底层const,都可以使用。 - dynamic_cast
支持运行时类型识别 - const_cast
只能改变运算对象的底层const - reinterpret_cast
通常为运算对象的位模式提供较低层次的重新解释
4.12 运算符优先级表
百度一下你就知道