第4章 表达式

4.1 基础 左值右值 当一个对象被用作左值时,用的是对象的身份;当用作右值时,用的是对象的值 求值顺序 int i=f1()*f2(); //无法知道f1
4.1 基础
  • 左值右值

    当一个对象被用作左值时,用的是对象的身份;当用作右值时,用的是对象的值

  • 求值顺序

    int i=f1()*f2();		//无法知道f1()和f2()的计算顺序int j=0;
    cout<<j<<" "<<++j<<endl;
    //可能先计算++j,再计算j的值;也有可能反过来
    
  • 含复数的取模运算

    m % (-n) = m % n;
    (-m) % n = -(m % n);
    
  • 窄化转换问题

    int k=0;
    k=3.14;		//类型转换后赋值
    k={3.14};	//报错,发生窄化转换
    
  • 位运算符

    <<=		//左移并赋值
    >>=		//右移并赋值
    &=		//按位与并赋值
    ^=		//按位异或并赋值
    |=		//按位或并赋值
    
  • 递增与递减运算符

    • 前置:将对象本身作为左值返回
    • 后置:将原始值的副本作为右值返回
    • 两者的效率:前置版本把值加一后直接返回了改变后的运算对象;后置版本需要将原始值存储下来,以便返回未修改的内容。故建议 若不需要未修改的原始值,建议使用前置版本
    • *p++ 等价于 *(p++) ,因为后置递增/减优先级高于解引用
  • sizeof

    //格式
    sizeof (type);
    sizeof expression;
    ...
    Object *p;
    sizeof *p;		//成立,即使p未初始化,在这里对其解引用也是安全的//注意,对string和vector对象执行sizeof,只返回其固定部分大小,不会计算对象中的元素占了多少空间
4.2 类型转换
  • 算术转换

    • 整型提升:小整数类型转为较大的整数类型,前提是转换后的类型能容纳原类型的所有可能值
    • 对于有符号和无符号混用情况
      • 若无符号数不小于有符号数,则有符号类型转为无符号类型
      • 有符号数大于无符号数,如果无符号类型的所有可能值都能存放在有符号类型中,则将无符号类型转为有符号类型;反之,将有符号类型转为无符号类型
  • 命名的强制类型转换

    //格式
    cast_name <type> (expression);
    //cast_name所含的种类
    static_cast / dynamic_cast / const_cast / reinterpret_cast
  • static_cast

    任何具有明确定义的类型转换,只要不包含底层const,都可以使用,当执行显式的类型转换时,警告信息会关闭

  • const_cast

    //只能改变运算对象的底层const
    //利用const_cast可以去掉const性质
    //若对象本身不是一个常量,则可以通过const_cast强转,获得写权限
    const char *pc;
    char *p=const_cast<char*>(pc);	//成立,但是通过p写值时未定义的
  • reinterpret_cast

    //为运算对象的位模式提供较低层次上的重新解释
    //容易出错,不建议使用
    int *ip;
    char *pc=reinterpret_cast<char*>(ip);
    //pc指向的对象时int,而非char
    
  • 老版本的强制转换

    type (expression);		//函数风格
    (type) expression;		//C风格