【C++学习】基础知识:运算符

C++ 运算符

【C++学习】以w3cschool的教程为框架,记录总结C++Primer第五版的学习内容。

  • C++定义了一元运算符和二元运算符,除此之外,还有三元运算符。函数调用也是一种特殊的运算符,它对运算对象的数量没有限制。

算术运算符

  • 一元运算符的优先级最高,接下来是乘法和除法,优先级最低的是加法和减法;

  • 运算符都满足左结合律,运算对象和求值结果都是右值;

  • 取模运算符%的运算对象必须是整数,若m%n不等于0,则它的符号和m相同。

关系运算符

  • 关系运算符作用于算术类型或指针类型;
  • 比较对象的大小并返回布尔值,满足左结合律,运算对象和求值结果都是右值;
  • 包括==!=><>=<=

逻辑运算符

  • 逻辑运算符作用于任意能转换成布尔值的类型;
  • 返回布尔值,运算对象和求值结果都是右值;
  • 包括&&||!

位运算符

  • 位运算符作用于整数类型的运算对象,并逐位执行操作;

  • 假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:

    A = 0011 1100

    B = 0000 1101

运算符 描述 实例
& 如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中。 (A & B) 将得到 12,即为 0000 1100
| 如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中。 (A | B) 将得到 61,即为 0011 1101
^ 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中。 (A ^ B) 将得到 49,即为 0011 0001
~ 二进制补码运算符是一元运算符,具有"翻转"位效果。 (~A ) 将得到 -61,即为 1100 0011,2 的补码形式,带符号的二进制数。
<< 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 A << 2 将得到 240,即为 1111 0000
>> 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 A >> 2 将得到 15,即为 0000 1111

赋值运算符

  • 赋值运算符的左侧对象必须是一个左值,赋值运算的结果是它的左侧对象,并且也是一个左值;

  • 如果左右两个运算对象类型不同,则右侧对象将转换为左侧运算对象的类型;

  • 赋值运算符满足右结合律

  • 赋值运算的优先级相对较低,所以通常需要给赋值部分加上括号;

  • 包括=+=-=*=/=等。

递增和递减运算符

  • 前置版本++a:先将运算对象加1,然后将改变后的对象作为求值结果;
  • 后置版本a++:将运算对象加1,但求值结果是运算对象改变之前那个值的副本;
    • 后置递增运算符的优先级高于解引用运算符;
    • 尽量不要使用后置运算符。

成员访问运算符

  • 点运算符:获取类对象的一个成员(*ptr).mem
    • 由于解引用运算符的优先级低于点运算符,所以执行解引用运算的子表达式两端必须加上括号;
  • 箭头运算符:与点运算符有关,ptr->mem等价于(*ptr).mem

sizeof运算符

  • sizeof运算符返回一条表达式或一个类型名字所占的字节数;
  • 满足右结合律,所得的值是一个size_t类型的常量表达式;
  • sizeof并不实际计算其运算对象的值;
  • sizeof运算符结果部分地依赖于其作用的类型:
    • 对引用类型得到被引用对象所占空间的大小;
    • 对指针类型得到指针本身所占空间的大小,对解引用类型得到指向对象所占空间的大小;
    • 对数组得到整个数组所占空间的大小;
    • 对string和vector得到该类型固定部分的大小,不会计算对象中的元素占用了多少空间。

类型转换

  • 算术类型之间的隐式转换被设计得尽可能避免精度损失:

    • 运算符的运算对象将会转换成最宽的类型;
    • 表达式中既有浮点类型也有整数类型时,整数类型将会转换成相应的浮点类型;
  • 其他隐式转换类型:

    • 数组自动转换成指向数组首元素的指针(p143):

      int ia[10];
      int *p = ia;
      

      当数组被用作decaltype的参数,或作为取地址符、sizeof等运算符的对象时,上述转换不会发生;

    • 常量整数值0或字面值nullptr能转换成任意指针类型;

    • 指向任意非常量的指针能转换为void,指向任意对象的指针能转换为const void;

  • 显示转换

    • 命名的强制类型转换:

      cast-name<type>(expression);
      
    • static_cast

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

      double slope = static_cast<double>(j) / i; //表示不在意潜在的精度损失
      
    • const_cast

      只能改名运算对象的底层const;

      对于将常量对象转换成非常量的行为,称之为“去掉const性质”

你可能感兴趣的:(C++学习,c++)