第四章 表达式
表达式由一个或多个运算对象组成,对表达式求值将得到一个结果。运算对象转换:小整数类型通常会被提升成较大的整数类型,主要是int。
- 重载运算符
- 左值和右值。可以做一个简单的归纳:当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。
- 已经有几种我们熟悉的运算符是要用到左值的:取地址符作用于一个左值运算对象,返回一个指向该运算对象的指针,这个指针是一个右值。 内置解引用运算符的求值结果是左值。
- 如果表达式的求值结果是左值,decltype作用于该表达式(不是变量)得到一个引用类型。但是我没有搞清楚decltype(&p)的结果是int **。
- 有四种运算符明确规定了运算对象的求值顺序第一种是逻辑与运算符,它规定先求左侧运算对象的值,只有当左侧运算对象的值为真时才继续求右侧运算对象的值。
4.3 逻辑和关系运算符
当布尔值转换成其他算术类型时,false转换成0,而true转换成1.
- 关系运算符满足左结合律,赋值运算符满足右结合律。 而赋值运算返回的是其左侧运算对象。赋值运算符优先级较低
- 再一次回顾一下默认初始化:定义于任何函数体之外的变量被初始化为0. 定义在函数体内部的内置类型变量将不被初始化。
- 0这个值可以赋给任何对象
练习4.16: 改为if((p=getPtr())!=0) if(i==1024)
4.5 递增和递减运算符
- 前置版本,这种形式的运算符首先将运算对象加1(或减1),然后将改变后的对象作为求值结果。前置版本将对象本身作为左值返回,后置版本则将对象原始值的副本作为右值返回。
- 后置递增运算符的优先级高于解引用运算符,因此*pbeg++等价于*(pbeg++)。简洁是一种美德。
- 解引用运算符的优先级低于点运算符。
- 条件运算符满足右结合律,意味着运算对象一般按照从右向左的顺序组合。
练习4.22:
int grade;
string finalgrade;
while (cin >> grade) {
if (grade > 100 || grade < 0) {
cout << "Not a valid data!" << endl;
break;
}
finalgrade = (grade > 90) ? "high pass"
: (grade < 75) ? (grade < 60) ? "fail" : "low pass"
: "pass";
cout << finalgrade << endl;
}
移位运算符:左移运算符在右侧插入值为0的二进制位。右移运算符的行为则依赖于左侧运算对象的类型:如果该运算对象是无符号类型,在左侧插入值为0的二进制位。如果该运算对象是带符号类型,在左侧插入符号位的副本或值为0的二进制位。
使用位运算符:unsigned long至少有32位.unsigned int至少16位。左移运算符的优先级要高于位或。
练习4.25 位取反的优先级在左移运算符之前。 优先级从高到底:位取反 ,左移 ,位或。
练习4.26 int类型只能确保占用16位,左移27位的话会产生未定义的行为。
移位运算符满足左结合律。注意:重载运算符的优先级和结合律都与它的内置版本一样。移位运算符的优先级不高不低,介于中间。
4.9 sizeof运算符
sizeof *p .sizeof运算符不会实际求运算对象的值,所以即使p是一个无效的指针也不会有什么影响。
逗号运算符含有两个运算对象,按照从左向右的顺序依次求值。
4.11.1 算数转换
整型提升:整型提升负责把小整数类型转换成较大的整数类型。如果一个运算对象是无符号类型,另外一个运算对象是带符号类型,而且其中的无符号类型不小于带符号类型,那么带符号的运算对象转换成无符号的。其他隐式类型转换:数组转换成指针,
指针的转换,指向任意非常量的指针能转换成void *.
转换成布尔类型,
转换成常量:允许将指向非常量类型的指针转换成相应的常量类型的指针,对于引用也是这样;
类类型定义的转换,之前的程序使用到类类型转换的地方:
string s, t="a value";
while(cin>>s) //while的条件部分把cin转换成布尔值
练习4.34: a. float转换成bool b. int值转换成float, 相加后的结果再转换成double c.cval先提升为int,再转换成double.
练习4.35 ‘a'是一个char型的字符常量,char类型的值首先被提升为Int,然后再转为char。
4.11.3 显示转换
命名的强制类型转换:
再回顾一下底层const:表示指针所指的对象是一个常量。名词顶层const:表示指针本身是一个常量。
static_cast,任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast.
const_cast,只能改变运算对象的底层const.