Skip to main content

第 4 章:表达式

表达式由一个或多个运算对象(operand)组成,对表达式求值将得到一个结果(result)

4.1 基础

  • 组合运算符和运算对象
  • 运算对象转换
  • 重载运算符(overloaded operator)
    • IO 库的 >><<
    • string、vector、迭代器的运算符
  • 左值、右值
    • 当对象用作右值,用的是对象的值(内容)
    • 当对象用作左值,用的是对象的身份(内存位置)

4.2 算术运算符

优先级从高到低排列。

4.3 逻辑运算符和关系运算符

if (val) 会把 val 转成布尔值,val 任意非 0 为真

if (!val) 会把 val 转成布尔值,val 为 0 为真

if (val == true) 与布尔值比较时,只有当 val 为 1 时才是真

4.4 赋值运算

赋值运算符的左侧运算对象必须是一个可修改的左值

赋值运算满足右结合律

int ival, jval;
ival = jval = 0;

可以看作是 ival = (jval = 0)jval = 0 该赋值运算返回左侧运算对象即 jval,所以 jval 又被赋给了 ival

因为赋值运算符的优先级低于关系运算符的优先级,所以在条件语句中,赋值部分通常应该加上括号。

4.5 递增递减运算符

递增和递减运算符有两种形式:前置版本和后置版本。

int i = 0, j;
j = ++i; // j = 1, i = 1; 前置版本得到递增后的值
j = i++; // j = 1, i = 2; 后置版本得到递增前的值

前置版本:得到递增后的值,即对象本身的左值(避免了不必要的工作)

后置版本:得到递增前的值,即对象原始值的副本作为右值(如果不需要修改前的值,那后置操作比较浪费)

下面这种情况比较适合使用后置版本,可以理解为 *(iter+)

cout << *iter++ << endl;

4.6 成员访问运算符

点运算符((*ptr).men)和箭头运算符(ptr->men)都可用于访问成员。

箭头运算符作用于一个指针类型的运算对象,结果是一个左值。

4.7 条件运算符

cond ? expr1 : expr2

4.8 位运算符

关于符号位如何处理没有明确的规定,所以强烈建议仅将位运算符用于处理无符号类型。

4.9 sizeof 运算符

sizeof (type);
sizeof expr;

4.10 逗号运算符

都要运算符首先对左侧表达式求值,然后将结果丢掉,结果是右侧表达式的求值结果。

4.11 类型转换

有时候类型是自动执行的,被成为隐式转换 implicit conversion。

  • 比 int 小的整型提升为较大整型
  • 在条件中非布尔值转布尔类型
  • 初始化时,初始值转为变量类型。赋值时,右侧对象转为左侧对象的类型
  • 在算术或关系运算中有多种类型,需要转换成同一种类型
  • 函数调用也会发生类型转换

算术转换

整型提升

  • 小整数类型提升为 int
  • 较大的 char 类型提升为 int、unsigned int、long、unsigned long、long long、unsigned long long 中最小的一种类型。

无符号类型

一般有符号类型提升为无符号类型

其他隐式类型转换

  • 数组转指针: int ia[10]; int *ip = ia;
  • 指针的转换 :0nullptr 能转换成任意指针,任意非常量指针能转换成 void*,任意指针能转换成 const void*
  • 转换成布尔类型:从算术类型或指针类型转为布尔类型
  • 转换成常量:非常量指针转换为常量指针
  • 类类型定义转换: while (cin >> str) io 库定义的 istream 向布尔值转换的规则

显式转换

有时候希望显式的将对象强制转换为另外一种类型。

cast-name<type>(expression)

cast-name 是 static_cast、dynamic_cast、const_cast、reinterpret_cast

static_cast

任何具有明确定义的类型转换,只要不包含底层 const,都可以用 static_cast<double>(ival)

const_cast

将常量对象转为非常量对象

reinterpret_cast

为运算对象的位模式提供较低层次上的重新解释。

reinterpret_cast 本质上依赖于机器。要想安全地使用reinterpret_cast必须对涉及的类型和编译器实现转换的过程都非常了解。

建议:避免强制类型转换

旧式的强制类型转换

type (expr); // 函数形式
(type) expr; // c 语言风格

4.12 运算符优先级