文章目录
C++primer学习心得-第四章-表达式
4.1 基础
1. 基本概念
- 一元运算符 :作用于一个运算对象的运算符,如 取地址符(&)和解引用符(*)
- 二元运算符:作用于两个运算对象的运算符,如相等运算符(==)和乘法运算符(*)
- 三元运算符:…三个…
对于有多个运算符的复杂表达式来说,运算符的优先级、结合律和运算对象的求值顺序就需要理解。
在表达式的求值的过程中常常伴随中运算对象的类型转换。
重载运算符:当运算符作用于类类型的运算对象时用户可以自行定义其含义。重载运算符时,运算对象的类型和返回值的类型都是由运算符定义的,但运算对象的个数、运算符的优先级和结合律都是无法改变的。
不同的运算符对运算对象的要求各不相同,有点需要左值运算对象,有点需要右值运算对象。
2. 优先级和结合律
程序员可以用括号将表达式的某个局部括起来使其得到优先运算。
优先级的重要性是毋庸置疑的。
需要注意的是,对于那些没有指定执行顺序的运算符来说,如过表达式指向并修改了同一对象,将会引发未定义的错误。
4.2 算术运算符
- +
- -
- *
- /
- %
注意整数相除的结果还是整数,小数部分直接去掉。
%为取余运算符,运算对象必须是整数。
4.3 逻辑和关系运算符
- !
- &&
- ||
- <,<=,>,>=
- ==
- !=
4.4 赋值运算符
注意:赋值运算符满足右结合律。
int i,j;
i=j=0;
靠右的赋值运算j=0先执行,由于赋值运算返回左侧运算对象,所以i,j都被赋值为0。
注意分清相等运算符和赋值运算符。
还有复合赋值运算符:
+= -= *= /= %=
<<= >>= &= ^= |=
等价于
a=a op b;
4.5 递增和递减运算符
int i=0,j;
j=++i;//j=1,i=1
j=i++;//j=1,i=2
建议使用前置版本。
4.6 成员访问运算符
箭头运算符和点运算符
ptr->men等价于(*ptr).men
注意解引用运算符的优先级低于点运算符,所以需要加括号。
4.7条件运算符
条件运算符(?:)允许我们将简单的if-else逻辑嵌入单个表达式中,形式为:
cond?expr1:expr2;
如
string finalgrade=(grade<60)?"fail":"pass";
嵌套条件运算
string finalgrade=(grade>90)?"high pass":(grade>60)"pass":"fail";
4.8 位运算符
- ~ 位求反
- << 左移
- >> 右移
- & 位与
- ^ 位异或
- | 位或
4.9 sizeof运算符
sizeif运算符返回一条表达式或一个类型名字所占的字节数。sizeof满足右结合律,返回值为size_t类型的常量表达式。
4.10 逗号运算符
逗号运算符含有两个运算对象,按照从左向右的顺序求值。
4.11类型转换
在以下情况下编译器会自动转换运算对象的类型:
- 通常,比int类型小的整型值首先提升为较大的整数类型
- 条件中,非布尔值转换为布尔类型
- 初始化时初始值转换为变量的类型,赋值时右值转换为左值的类型
- 算术或关系运算对象有多种类型需要转换为一种类型
- 函数调用时也会发生类型转换
1. 算术转换
算术转换是把 一种算术类型转换为另一种算术类型。具体怎么转换需要做很多尝试才知道。
2.显示转换
命名的强制类型转换具有以下形式:
cast-name(expression)
type是转换的目标类型,expression是要转换的值。
cast-name是static_cast、dynamic_cast、const_cast、reinterpret_cast中的一种。
- static_cast:任何具有明确定义的类型转换,只要不包含底层const
- dynamic_cast:支持运行时类型识别
- const_cast:只能该别运算对象的底层const(常量转换为非常量)
- reinterpret_cast:为运算对象的位模式提供较低层次上的重新理解
强制类型转化会干扰正常的类型检查,我们建议避免使用。
旧式的强制类型转换:
type(expr) 函数形式的强制类型转换
(type)expr c语言风格的强制类型转换