表达式基础
- 重载运算符:当运算符作用于类类型的运算对象时,用户可以自行定义其含义。
- 左值和右值:
- C中原意:左值可以在表达式左边,右值不能。
C++
:当一个对象被用作右值的时候,用的是对象的值(内容);- 当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。
- 解引用运算符生成左值,decltype(*p)的结果为
int &
- 取地址符生成右值,decltype(&p)的结果为
int **
,是一个指向整型指针的指针
逻辑运算符
- 短路求值:逻辑与运算符和逻辑或运算符都是先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧运算对象的值。
赋值运算符
- 如果赋值运算的左右侧运算对象类型不同,则右侧运算对象将转换成左侧运算对象的类型。
- 赋值运算符满足右结合律,这点和其他二元运算符不一样。
ival = jval = 0;
等价于ival = (jval = 0);
- 赋值运算优先级比较低。
说明前置递增运算符和后置递增运算符的区别。
b前置递增运算符将对象本身作为左值返回,而后置递增运算符将对象原始值的副本作为右值返回。
假设iter
的类型是vector::iterator
, 说明下面的表达式是否合法。如果合法,表达式的含义是什么?如果不合法,错在何处?
(a) *iter++;
(b) (*iter)++;
(c) *iter.empty();
(d) iter->empty();
(e) ++*iter;
(f) iter++->empty();
(a)合法。返回迭代器所指向的元素,然后迭代器递增。
(b)不合法。因为vector元素类型是string,没有++操作。
(c)不合法。这里应该加括号。
(d)合法。判断迭代器当前的元素是否为空。
(e)不合法。string类型没有++操作。
(f)合法。判断迭代器当前元素是否为空,然后迭代器递增。
移位运算符满足左结合律
sizeof运算符
- 返回一条表达式或一个类型名字所占的字节数,满足右结合律。返回的类型是
size_t
。 - 两种形式:
sizeof (type)
和sizeof expr
逗号运算符
- 含有两个运算对象,按照从左向右的顺序依次求值
隐式类型转换
- 比
int
类型小的整数值先提升为较大的整数类型。 - 条件中,非布尔转换成布尔。
- 初始化中,初始值转换成变量的类型。
- 算术运算或者关系运算的运算对象有多种类型,要转换成同一种类型。
- 函数调用时。
显式类型转换(尽量避免)
- static_cast:任何明确定义的类型转换,只要不包含底层const,都可以使用。
double slope = static_cast<double>(j);
- dynamic_cast:支持运行时类型识别。
- const_cast:只能改变运算对象的底层const,一般可用于去除const性质。
const char *pc; char *p = const_cast<char*>(pc)
- reinterpret_cast:通常为运算对象的位模式提供低层次上的重新解释。
说明下面这条表达式的含义。
double slope = static_cast<double>(j/i);
将j/i的结果值转换为double,然后赋值给slope