- 表达式:一个或多个运算对象组成。
最简单的表达式是:字面值和变量。 - 运算符:
2.1 一元运算符(作用于一个对象)
二元运算符
三目运算符
2.2 运算符的优先级、结合律、运算对象的求值顺序,运算对象的转换
2.3 重载运算符:如IO 的<<、>>、string,vector等的迭代器
2.4 左、右值:一个左值表达式 的求值结果是一个对象或一个函数。
当一个对象被用作右值时,用的是对象的值(内容),当对象 被用作左值时,用的是对象的身份(内存中的位置)
注1:使用decltype()的时候,左值和右值不同。表达式的结果是左值,使用decltype后得到引用类型,如解引用运算符。当表达式的结果是右值时,如取地址运算符(作用于左值a,表达式结果&a为右值,一个指向该运算对象的指针)
int *p=&a;//解引用运算符生成左值。
decltype(*p);//该表达式的结果是 int&;
decltype(&p);//该表达式的结果是int **,指向整形指针的指针。
decltype(&a);//该表达式的结果是int *,指向a的指针
注2:
1)赋值运算符 = 需要一个左值(非常量的)作为该运算符的左侧运算对象,得到的结果也是一个左值。
2)取地址符:作用于左值运算对象,返回一个指向该运算对象的指针,该指针是一个右值。
3)内置解引用运算符、下标运算符 等求值结果都是左值,
4)内置类型和迭代器的递增递减运算符作用于左值,前置时结果也是左值。
2.2.1 优先级与结合律:
优先级相同,按从左到右的顺序
括号
优先级表:同一组内的运算符优先级相等,组的位置越靠前优先级越高
2.2.2 运算对象的求值顺序:
大多数情况下,不会明确指明求值顺序。
表达式指向并修改了同一对象,会发生错误,如:
cout<<i<<" "<<++i<<endl;
4种明确规定了运算对象的顺序的运算符:逻辑与(&&)、逻辑或(||)、条件(?:)、逗号运算符(,)。
- 算术运算符:
算术运算符:作用于:任意算术类型及任意能转换成算术类型的类型。
运算对象和求值结果都是右值,求值之前一个表达式里所有的运算会转换成同一类型。
算术表达式的异常:溢出,除数为0。
注:1)参与取余运算的运算对象必须是整数。
2)int/int 结果还是int。舍弃小数部分,
3)m%n,结果的符号与m相同。
- 逻辑和关系运算符:
逻辑运算符和关系运算符都返回 布尔类型
关系运算符作用于:算术类型、指针类型
逻辑运算符作用于:任意能转换成布尔值的类型
运算对象与求值结果都是右值。
逻辑与和逻辑或:短路求值
关系运算符都满足:左结合律
注意关系运算符不能连用。
- 赋值运算符:
赋值运算符的左侧必须是 : 可修改的左值
int i =0;//初始化,非赋值
const int ci = i;//初始化,非赋值
1024 = i;//错,字面值是右值
i+j = k;//算术表达式是右值
ci = k;//ci是常量
如果赋值运算符的左侧运算对象是 内置类型(整型数、浮点数、字符、布尔、void、枚举),则初始化列表最多包含一个值。
赋值运算 满足右结合律,赋值运算的结果是他的左侧运算对象,且是一个左值,当赋值运算符左右两侧的类型不同,右侧的转换为左侧的类型
int i,j;
i=j=0;//靠右的赋值运算j=0作为靠左的赋值运算符的右侧运算对象。
//赋值运算返回左侧运算对象,靠右的赋值运算的结果(j=0)赋给i
int i,*p;
i=p=0;//错误,p是指针,不能作为右值赋给int型的i
赋值运算符的优先级较低,与其他运算符混用时,应该注意加括号。
- 递增、递减运算符:
int i=0,j;
j=++i;//i=1,j=1
j=i++;//i=2,j=1
前置得到相加之后的值
后置得到相加之前的值
尽量用前置版本,当既需要把某一个值加1,且还要使用加之前的值,使用后置版本。
后置的递增运算符的优先级高于解引用运算符:
递增运算符改变了某个运算对象的值,所有在复合语句中,要小心使用,注意运算顺序。
*beg = toupper(*beg++);//错误,赋值语句左右都用到了beg,右侧又改变了beg,
*beg=toupper(*beg);
++beg;
-
成员访问运算符:
点运算 . 和箭头运算 -> 都可以访问 成员
(*p).men() 等价于 p->men() -
条件运算符:满足右结合律
即三目运算符:?:
条件?表达式1:表达式2
条件成立返回表达式1,不成立返回表达式2
可以嵌套,不宜超过3层
(grade>90)?“youxiu”:(grade>60)?“pass”:failed"
- 位运算符:
作用于整数类型的运算对象 ,并把运算对象看成是 二进制位 的集合,最好只作用于 无符号的整数类型。
注:输入输出的<< >>等是标准IO库对位运算符的重载,这两种运算符的内置含义是对其运算对象进行基于二进制位的移动操作。
令左侧运算对象的内容按照 右侧运算对象的要求移动指定的位数(可能会进行类型提升),将移动后的左侧运算对象作为求值结果。右侧运算对象不能为负,且值必须小于结果(有可能进行提升)的位数。