C++ Primer第四章表达式 表达式由一个或多个运算对象(operand)组成,对表达式求值将得到一个结果。 基础 一元运算符(*,&) 二元运算符(*,+,-) 组合运算符和运算对象 对于含有多个运算符的复杂表达式来说,要想理解它的含义首先要理解运算符的优先级,结合律以及运算对象的求值顺序。 运算对象的转换,比如整数转换成浮点数。 重载运算符 C++定义了运算符作用域内置类型和复合类型的运算对象时所执行的操作。 当运算符作用于类类型的运算对象时,用户可以自行定义其含义称之为重载运算符。 左值和右值 C++的表达式要么是右值要么是左值。左值可以位于赋值语句的左侧而右值则不能。 当一个对象被用作右值的时候,用的是对象的值,当对象被用作左值的时候,用的是对象的身份(在内存中的位置) 一个中要的原则是在需要右值的地方可以用左值来代替,但是不能把右值当成左值使用,当一个左值被当成右值使用时,实际使用的是它的内容。 1)赋值运算符需要一个(非常量)左值作为其左侧运算对象,得到的结果也仍然是一个左值。 2)取地址符作用于一个左值运算对象,返回一个指向该元算对象的指针,这个指针是一个右值。 3)内置解引用运算符,下标运算符,迭代器解引用运算符,string,vector的下标运算符的求值结果都是左值 4)内置类型和迭代器的递增递减运算符作用域左值对象所得的结果也是左值。 5)使用关键字decltype的时候,左值和右值也有所不同,如果表达式的求值结果是左值,decltype作用于该表达式得到一个引用类型int *p;decltype(*p)得到的是int&而decltype(&p)得到的是int** 优先级和结合律 求值顺序 优先级规定了运算对象的组合方式但是没有说明运算符对象按照什么顺序求值。 int i = f1() * f2(); 有四种运算符明确规定了运算符的求值顺序。 && 先求左侧运算对象的值为真时才继续求右侧的值 || ,?:, ,逗号运算符 一条形如 f()+g()*h()+j()的表达式对函数的调用顺序并没有规定因此结果是未定义的。 处理复合表达式 1拿不准的时候最好用括号来强制让表达式的组合关系符复合程序逻辑的要求。 2如果改变了某个运算对象的值,在表达式的其他地方不要再使用这个运算对象 算术运算符 +,-(一元正负号),*,/,%,+,- 一元运算符优先级最高然后是乘除接下来是加减 溢出由于内置类型有范围限制,当值超出范围时就会溢出。 逻辑和关系运算符 关系运算符作用于算术类型或指针类型,逻辑运算符作用于任意能转换布尔值的类型。 !,<,<=,>,>= ==,!=,&&,|| 逻辑与和逻辑或元算服都是先求左侧运算对象的值再求右侧运算对象的值这种策略称为短路求值。 赋值运算符 赋值运算符的左侧运算对象必须是一个可修改的左值 int i = 0,j = 0,k = 0;//初始化而非赋值 const int ci = i;//初始化 初始化和赋值的区别是初始化是分一块内存同时将值填进去,赋值是分一块内存(随机值)之后赋值覆盖。 赋值符满足右结合律 ival = jval = 0; 复合运算符 +=,-=,*=,/+,%=,<<=,>>=,&=,^=,|=; 任意一种复合运算符都完全等价于a = a op b; 递增和递减运算符 前置++,--和后置++,-- 前置是返回临时对象然后同时对自己+1 后置+1后返回 成员访问运算符 点运算符和箭头运算符都可用于访问成员。 ptr->mem;(*ptr).mem; 条件运算符 cond?expr1:expr2; 条件运算符的运算级别比较低所以要在两端加括号。 位运算符 位运算符作用域整数类型的运算对象并把运算对象堪称是二进制位的集合。 标准库的bitset ~按位求反 <<左移 >>右移 &位与 ^位异或 |位或 左移操作可能会改变符号位 sizeof运算符 sizeof(type) sizeof expr sizeof并不实际计算其运算对象的值 对chae或者类型为char的表达式执行sizeof运算结果为1 对引用类型执行sizeof运算得到的是被引用对象所占空间的大小 对指针执行sizeof运算得到的是指针本身所占的空间大小 对解引用指针执行sizeof运算得到的是指针指向的对象所占空间的大小,指针不需要有效。 对数组执行sizeof运算得到整个数组所占空间的大小,sizeof不会把数组转换成指针来处理 对string对象或vector执行sizeof运算只返回该类型固定部分的大小不会计算对象中元素占用了多少空间。 逗号运算 含有两个运算对象,按照从左向右的顺序依次求值。 首先对左侧的表达式求值然后将求值结果丢弃掉.逗号运算符真正的结果是右侧表达式的值。如果右侧运算对象是左值,那么最终的求值结果也是左值。 类型转换 算术类型之间的隐式转换被设计得尽可能避免损失精度。整型会转换成浮点数 何时发生隐式转换 在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型 在条件中,非布尔值转换成布尔值 初始化过程中,初始值转换成变量的类型,在赋值语句中,右侧运算对象转换成左侧运算对象的类型 如果算术运算或关系运算的运算对象有多种类型需要转换成同一种类型 函数调用式时会发生类型转换。 整数提升,小整数并提升为大整数 无符号类型运算对象依赖于整数类型的相对大小 数组转换成指针。数组自动转换成指向数组首元素的指针。 显式转换(强制类型转换) static_cast,dynamic_cast,const_cast,reinterpret_casr static_cast 任何具有明确定义的类型转换只要不包含底层const都可以使用static_cast const_cast只能改变运算符底层const reinterpret_cast为运算对象的位模式提供较低层次上的重新解释 dynamic_cast运行时判断继承类之间的转换 |
|
来自: dongtongtong > 《C Primer(第五版)》