C++ Primer_第四章_表达式

基本概念

基础

什么是表达式

由一个或多个运算对象组成的,且计算可得一个结果,字面值和变量是最基本的表达式

运算符

表达式中连接多个运算对象的被称为运算符。根据作用的运算对象的数量,运算符分为一元运算符二元运算符三元运算符。一些符号可以是多种,比如*函数调用也是一种运算符,对运算对象没有限制。

组合运算符和运算对象的类型转换

  • 一个表达式含有多个运算符时,需考虑优先级结合律运算对象的求值顺序
  • 运算对象的类型可以不一样,类型的转换规则

运算符的重载

除C++语言定义的用于内置类型和复合类型的操作外,例如>><<stringvector的运算符等,用户可以定义用于类对象的含义。在重载运算符时,可以自定义运算对象返回类型,而运算对象的个数、优先级和结合律无法更改。

左值和右值

  • C++中的表达式要么是左值,要么是右值;
  • 当一个对象被用作右值时,用到是对象的值(内容);当用作左值时,用的是对象的身份(在内存中的位置)
  • 左值可以用在需要右值的地方;反之不行
  • 需要左值的地方:1.赋值运算符左侧需要左值,得到的结果也是左值;2.取地址符;3.内置解引用运算符下标运算符迭代器解引用运算符内置类型和迭代器的递增递减运算符
  • 使用关键字 decltype 时,如果表达式的求值结果是左值, decltype 作用于该表达式(不是变量)得到一个引用类型。

优先级与结合律

如果运算符优先级相同,按照从左向右的顺序组合运算对象。大部分二元运算符满足左结合律,赋值运算符满足右结合律。括号无视优先级与结合律。

求值顺序

  • 在一个复合表达式中,各个运算对象的求值顺序是不固定的。例如int i=fun1()*fun2()中并不知先调用fun1还是fun2
std::cout << i << ++i << std::end;//错误!未定义的行为,不知道先求 i 还是先求 ++i
  • 4种运算符明确规定了运算对象的求值顺序:逻辑与(&&,先左后右)、逻辑或(||,先左后右)、条件(?:,先条件,再分支)、逗号(,从左向右)
  • 处理复合表达式的两个建议:
    (1)不确定优先级与结合律时使用括号;
    (2)如果改变了某个运算对象的值,在同一表达式中不要再使用该运算对象。

类型转换

  • c++ 不会直接将两个不同类型的值相加,会先通过类型转换把运算对象的类型统一后再求值。
  • 隐式类型转换的发生场景
    (1)比 int 类型小的整型值首先提升为较大的整数类型;
    (2)在条件里,把非布尔值转换成布尔值;
    (3)初始化过程中,初始值转换为变量的类型;
    (4)赋值时,右侧运算对象转换成左侧类型;
    (5)算数运算或关系运算的运算对象有多种类型,转换成一种。
  • 算式转换
    运算符的运算对象将转换成所有运算对象中最宽的类型。如果表达式中既有整型也有浮点型,一般会把整型转换为浮点型。
3.14159L + 'a';//先将'a'提升成 int,然后把 int 转换成 long double
  • 整型提升
    (1)整型提升把小整数类型(包括 charbool等)转换成较大的整数类型。如果int可以就转换成int,否则提升成unsigned int类型。
    (2)如果一个是无符号一个带符号。如果无符号类型不小于带符号类型(比如都是 4 字节),则带符号转换为无符号.如果无符号类型小于带符号,转换结果依赖机器。尽量避免。
  • 其他隐式类型转换
  1. 数组转换成指针
    大多数情况下数组自动转换成指向数组首元素的指针。(decltype关键字参数、取地址符(&)、sizeoftypeid都不会发生这种转换)
  2. 指针的转换
    0nullptr都能转换成任意指针类型。指向非常量的指针能转换成void*。指向所有对象的指针都能转换成const void*
  3. 转换成常量
    指向非常量的指针转换成指向相应常量类型的指针
  4. 类类型定义的转换
while(cin>>s);//将 cin 转换为 bool 值
string s = "value";//将 c 风格字符串转换为 string
  • 显式转换(强制类型转换)

运算符优先级表

运算符优先级
运算符优先级

posted @ 2022-07-08 15:25  H_OLLEH  阅读(31)  评论(0)    收藏  举报