C++ Primer 学习——第四章:表达式

  |   0 评论   |   0 浏览

1. 基础

1.1 求值顺序

对于没有指定顺序的运算符,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为。

int i = 0;
cout<< i <<" "<<i++<<endl;  // 未定义的,表达式的行为不可预知

1.2 关系运算符

关系运算符返回布尔值且满足左结合律。

//用i < k的布尔值结果和k比较
if(i < j < k)    //k > 1时为真

1.3 赋值运算符

赋值运算符的左侧运算对象必须是一个可修改的左值,且满足右结合律。

int i; double d;
d = i = 3.5;     //i == 3, d == 3
i = d = 3.5;     //i == 3, d == 3.5

1.4 递增递减运算符

  • 后置和前置递增运算符
int i = 0,j;
j = ++i;         //j = 1, i = 1;
j = i++;         //j = 1, i = 2;
  • 在一条语句中混用解引用和递增运算符
auto pbeg = v.begin();
//输出元素直到遇到第一个负值为止
while(pbeg != v.end() && *pbeg)
  cout << *pbeg++ << endl;

本质上等价于*(pbeg++)。即将pbeg的值+1然后返回pbeg初始值的副本。

1.5 位运算符

  • 基本位运算符
  1. 位求反: ~
  2. 左移: <<
  3. 右移: >>
  4. 位或: |
  5. 位与: &
  6. 位异或: ^
  • 移位运算符
  1. 操作将运算符左侧对象按右侧对象要求移动指定位数,返回得到的新值。

  2. 左移在右侧添0,右移若为有符号数,左侧添符号位,若为无符号数,左侧添0。

  3. char类型会被提升为int类型。

  4. 位运算不改变原始值,具有返回值且返回值为运算后的新值。

unsigned char b1 = 0233;
b1 << 8;  
//b1左移8位

unsigned char b2 = 0145;
~ b2;                                             
//b2逐位取反,赋给b2

unsigned char b3 = 0145;
unsigned char b4 = 0257;
b3 & b4;
b3 | b4;
b3 ^ b4;
//b3和b4做位与,位或,位异或运算

unsigned int c = b3 | b4

  • 一个例子
  1. 假设班级有30个学生,用一个二进制位表示每个学生是否通过测验。全班的结果故可用一个unsigned long 表示。
unsigned long quiz = 0;
  1. 如果第二十七个同学通过了测验,修改结果的操作:
quiz |= 1UL << 27;
//1UL表示无符号长整型1
  1. 查询第二十七个同学是否通过
bool pass = quiz & (1UL << 27)

2. sizeof运算符

  • 对引用执行sizeof得到被引用对象所占空间大小。
  • 对指针执行sizeof得到指针本身所占空间大小。
  • 对解引用指针执行sizeof得到指针指向的对象所占空间大小。
  • 对数组执行sizeof返回的是整个数组所占空间大小。
  • 对vector或string执行sizeof只返回固定部分大小,不计算元素占用的空间。
  • 返回值单位为字节。

3. 类型转换

  • 隐式转换
  1. 算数转换
bool flag;     char cval;
int ival;      short sval;
long lval;     unsigned int uival;
unsigned short usval;
unsigned long ulval;
float fval;    double dval;

3.14159L + 'a'     //'a'提升为int,int 再转为long double。
dval + fval;       //fval转化为double。
dval + ival;       //ival转化为dval。
ival = dval;       //dval转化为切除小数部分后的ival。
flag = dval;       //dval为0 flag为false,dval为1 flag为true。
cval + fval        //cval提升为int,int再转化为float。
sval + cval;       //sval和cval均转化为int。
cval + lval;       //cval转化为long。
ival + ulval;      //ival转化为unsigned long。
usval + ival;      //根据unsigned short和int所占空间大小进行转换。
uival + lval;      //根据unsigned int 和龙所占空间大小进行转换。
  1. 其他隐式转换

    数组转为指针,指针间的转换,转换成bool,非常量转换为常量。

  • 显式转换
  1. 命名的强制类型转换

    转换格式:
    cast-name(expression)

    其中
    type 是转换的目标类型。
    expression 是要转换的值。
    cast-name 是static_cast、dynamic_cast、const_cast和reinterpret_cast中的一种。

    static_cast: 任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast。

    const_cast: const_cast只能改变运算对象的底层const。不可用于其他类型转换。

    const char *pc;
    char *p = const_cast<char*>(pc);       //正确,但通过p写值是未定义的行为。
    
    const char *cp;
    char *q = static_cast<char*>(cp);      //错误,static_cast不能改变const属性。
    static_cast<string>(cp);               //正确,将字符串的字面值转换成string。
    const_cast<string>(cp);                //错误 ,const_cast只能用于去常量化。
    

    reinterpret_cast: 为运算对象位模式提供较低层次的重新解释,使用十分危险。

2.旧式的强制类型转换

在早期的c++版本,显式进行强制类型转换有两种形式:

type (expr)

(type) expr


标题:C++ Primer 学习——第四章:表达式
作者:YaoCheng8667
地址:https://ycisme.xyz/articles/2019/12/05/1575527208497.html