表达式
表达式是由一个或者多个运算对象构成,运算对象之间可以通过运算符连接起来。对表达式求值最后都会得到一个结果。
几个概念
1、左值和右值
C++表达式要不是左值,要不就是右值。当一个对象被用作右值时用的是对象的值;当被用作左值时,用的是对象的存储空间。一个重要的原则:
左值可以当右值使用,但右值不可以当左值使用。
2、优先级
优先级和结合律决定了运算符和运算对象的集合方式,在复合表达式中很关键。
3、求值顺序
四种运算符规定了求值顺序:与(&&),或(||),条件(?:),逗号(,)。
对于没有规定求值顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为。
算数运算符
算数运算符满足左结合律,按照优先级从高到低依次为:一元正号(+),一元负号(-);乘法(*),除法(/),求余(%);加法(+),减法(-)。
1)整数相除还是整数;除法所得的商一律向0取整。
2)取余运算的运算对象必须是整数。m%(-n)= m%n ; (-m) % n = - (m % n)。
逻辑与关系运算符
逻辑运算符中的逻辑非满足右结合律,其余的逻辑运算符和关系运算符满足左结合律。优先级次序为:逻辑非(!);小于(<),小于等于( <= ),大于( > ),大于等于( >= );相等( == ),不相等( != );逻辑与( && );逻辑或(||)。
1)逻辑与和逻辑或有短路求值策略:当运算符左侧就能决定整个表达式的值时就不会计算右侧的表达式。
2)关系运算符的求值结果是布尔值。
赋值运算符
赋值运算符的左侧运算对象必须是一个可修改的左值。赋值运算符满足右结合律。
递增和递减运算符
递增运算符(++)和递减运算符(--)是对对象进行加1和减1的操作。
两种运算符分为前置版本和后置版本:前置版本是将运算对象先加1然后将改变后的对象作为求值结果;后置版本的求值结果是运算对象改变之前的那个值得副本。
成员访问运算符
点运算符( . )和箭头运算符( -> )都可以用于成员访问,其中点运算符获取类对象的一个成员。ptr->mem 等价于 (*ptr).mem。
条件运算符
条件运算符(?:)相当于简单的if-else语句,形势为: cond? expr1:expr2;
其中cond为条件,首先对其求值,若果cond条件为真,则返回expr1表达式的值,否则返回expr2的值。
条件运算符满足右结合律。
位运算符
位运算符的运算对象是整数类型,并且将运算对象作为二进制位的集合。优先级依次为:位求反(~);左移(<<), 右移(>>);位与(&);位异或(^);位或(|)。
移位运算符:
1)运算符的右侧不能为负值而且其值必须严格小于结果的位数;
2)移出边界之外的位被舍弃了;
3)左移运算符在右侧补0;
4)右移运算符在左侧补0或者符号位;
5)移位运算符 满足左结合律。
sizeof运算符
sizeof运算符返回一条表达式或者一个类型名字所占的字节数,满足右结合律,返回值是一个size_t类型的常量表达式。
sizeof 并不会对运算对象进行实际的求值运算。存在两种表达方式:
sizeof (type);
sizeof expr;
1)对char或者类型为char的表达式执行sizeof运算,其结果为1;
2)对引用类型进行sizeof操作得到的是被引用对象所占空间的大小;
3)对指针执行sizeof运算得到的是指针本身所占空间的大小;
4)对解引用指针执行sizeof运算得到的是指针所指对象所占空间的大小,其中指针并不一定需要有效;
5)对数组执行sizeof操作得到真个数组所占空间的大小;
6)对string或者vector对象执行sizeof操作只返回该类型固定部分的大小,不会计算其中元素占用的空间。
逗号运算符
逗号运算符按照从左到右依次求值,首先将左侧的表达式求值,然后将左侧表达式结果丢弃,再求右侧表达式结果的值,整个表达式的求值结果也是右侧表达式的值。