第四章:表达式
4.1 基础
1.表达式:由一个或多个运算对象组成,对表达式求值将得到一个结果,字面值和变量是最简单的表达式,讲一个运算符和一个或多个运算对象组合起来可以生成较为复杂的表达式。
2.左值和右值:当对象被用作左值的时候,用的是对象的身份(在内存中的位置);
当一个对象被用作右值时,用的是对象的值(内容)
使用关键字 decltype 时,左值和右值也有所不同,若表达式求值结果为左值,decltype 作用于该表达式得到一个引用类型。
int *p;
//解引用运算符生成左值,所以得到的结果为 int&
decltype(*p);
//取地址运算符生成右值,所以得到的结果为 int**
decltype(&p);
3.复合表达式:指含有两个或多个运算符的表达式,对于含有多个运算符的复杂表达式来说,要理解它的含义首先要理解运算符的优先级、结合律以及运算对象的求值顺序
1)左结合律:若运算符优先级相同,则按照从左到右的顺序组合运算对象
2)求值顺序:优先级规定了运算对象的组合方式,但没说明运算对象按照什么顺序求值,在多数情况不会明确指定求值顺序;
对于没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并昌盛未定义的行为;
有4种运算符明确规定了运算对象的求值顺序:
逻辑与( && )运算符:规定先求左侧运算对象的值,只有当左侧运算符为真时才继续求右侧运算对象的值
逻辑或( || )运算符:对顶先求左侧运算对象的值,只有左侧运算对象为假时擦对右侧运算对象求值
条件( ?: )运算符:先对条件进行判断,为真对表达式1计算,为假对表达式2计算
逗号(,)运算符:按照从左向右的顺序依次求值
3)求值顺序、优先级、结合律:运算对象的求值顺序与优先级和结合律无关,e g:表达式 f() + g() * h() + j()
优先级规定:g() 的返回值和 h() 的返回值相乘
结合律规定:f() 的返回值先与 g() 和 h() 的乘积相加,所得结果再与 j() 的返回值相加
求值顺序:对于这些函数的调用顺序没有明确规定
注:如果f、g、h、j是无关函数,既不会改变同一对象状态,也不执行IO任务,那么函数调用顺序不受限制,反之若其中几个函数影响同一对象则是错误表达式,将产生未定义行为
4.2 算术运算符
1.优先级:一元运算符优先级最高,之后是乘法和除法,加法和减法优先级最低
结合律:左结合律,优先级相同时按照从左到右的顺序结合
算数运算符的运算对象和求值结果都是右值
在表达式求值之前,小整数类型的运算对象被提升成较大的整数类型,所有运算对象最终会转换成同一类型
4.3 逻辑和关系运算符
1.运算对象和求值结果均为右值
逻辑与和逻辑或运算符都有明确的求值顺序
关系运算符都满足左结合律
2.进行比较运算时除非比较的对象是布尔类型,否则不要使用布尔字面值 true 和 false 作为运算对象
if(val) {
} //若val是任意非0值,条件为真
if(!val) {
} //若val是0,条件为真
if(val == true) {
} //只有当 val 为1时为真
4.4 赋值运算符
1.赋值运算符的左侧运算对象必须是一个可修改的左值
int i = 0, j = 0, k = 0; //初始化而非赋值
const int ci = i; //初始化而非赋值
i + j