<C++学习十五>C++运算符

摘要: 本篇博客仅作为笔记,如有侵权,请联系,立即删除(网上找博客学习,然后手记笔记,因纸质笔记不便保存,所以保存到网络笔记)

  运算符是一种告诉编译器执行特定的数字或逻辑操作的符号。C++内置了丰富的运算符,并提供了以下类型的运算符:

  算术运算符    关系运算符    逻辑运算符

  位运算符        赋值运算符    杂项运算符

1、算术运算符

算术运算符
运算符 描述
+ 把两个操作数相加
- 从第一个操作数中减去第二个操作数
* 把两个操作数相乘
/ 分子除以分母
% 取模运算符,整除后的余数
++ 自增运算符,整数值增加1
-- 自减运算符,整数值减少1

 2、关系运算符

关系运算符
运算符 描述
== 检查两个操作数的值是否相等,如果相等则条件为真
!= 检查两个操作数的值是否相等,如果不相等则条件为真
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真
< 检查左操作数的值是否小于右操作数,如果是则条件为真
>= 检查左操作数的值是否大于等于右操作数的值,如果是则条件为真
<= 检查左操作数的值是否小于等于右操作数的值,如果是则条件为真

3、逻辑运算符

逻辑运算符
运算符 描述
&& 称为逻辑与运算符。如果两个操作数都非零,则条件为真
|| 称为逻辑或运算。如果两个操作数中有任意一个非零,则条件为真
! 称为逻辑非运算符,用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假

4、赋值运算符

赋值运算符
运算符 描述
= 简单的赋值运算符,把右边操作数的值赋给左边操作数
+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数
-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数
*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数
/= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数
%= 求模且赋值运算符,求两个操作数的模赋值给左边操作数
<<= 左移且赋值运算符
=>> 右移且赋值运算符
&= 按位与且赋值运算符
^= 按位异或且赋值运算符
!= 按位或且赋值运算符

5、位运算符

位运算符
运算符 描述
& 如果同时存在于两个操作数中,二进制AND运算符复制一位到结果中
| 如果存在任一操作数中,而精致款OR运算符复制一位到结果中
^ 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中
~ 二进制补码运算符是一元运算符,具有“翻转”位效果,即0变成1,1变成0
<< 二进制左移运算符,左操作数向左移动右操作数指定的位数
>> 二进制右移运算符,左操作数向右移动右操作数指定的位数

6、杂项运算符

杂项运算符
运算符 描述
sieof sieof运算符返回变量的大小
condition?x:y 条件运算符
, 逗号运算符会执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值
. / -> 成员运算符用于引用类、结构和共用体的成员
cast 强制转换类型运算符把一种数据类型转换成另一种数据类型。
& 指针运算符&返回变量地址
* 指针运算符*指向一个变量

关于C++中的运算符优先级

  运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级。例如,乘除运算符具有比加减更高的优先级。

  下表按运算符从高到低列出各个运算符,具有较高优先级的运算符出现在表格上面,具有较低优先级的运算符出现在表格下面:

C++运算符优先级
类别 运算符 结合性
后缀 ()[]->.++-- 从左到右
一元 +-!~++--(type)*&sizeof 从左到右
乘除 */% 从左到右
加减 +- 从左到右
位移 << >> 从左到右
关系 < <= >= 从左到右
相等 == != 从左到右
位与AND & 从左到右
位异或XOR ^ 从左到右
位或OR | 从左到右
逻辑AND && 从左到右
逻辑OR || 从左到右
条件 ? : 从右到左
赋值 = += -= *= /= %= >>= <<= &= ^= |= 从右到左
逗号 , 从左到右

C++强制类型转换:

  C++中的强制类型转换虽然兼容C语言中的强制类型转换。但并不建议在C++中使用C语言风格的强制类型转换。C++中强制类型转换公有4个关键字分别是static_cast,const_cast,reinterpret_cast,dynamic_cast。

  static_cast:

  用于将一种类型转换成另一种类型,使用格式如下:

  变量1 = static_cast<变量1数据类型>(另一种数据类型变量或表达式)  

int a = 1;
float b = static_cast<float>(a); //类似于C语言中的b = (float)a

  const_cast:

  用于去除指针的常量性,不能去除变量的常量性。使用格式如下:

  指针或引用1 = const_cast<指针或引用1类型>(带常量性的指针或引用2)

int a = 10;
const int *p = &a;
int *q;
q = const_cast<int*>(p); //去除p的常量性给q,如果不去除直接赋值会报错

 总结:

  1、对变量a加上了const属性,因此a的值是不会被程序所改变的。即使我们将指向a的指针的const属性去掉重新复制也不会改变。但是会出现变量a与指针q指向地址相同,但值不同的现象。

  2、对变量b的操作我们可以看出,const_cast不仅仅能去掉指针的const,也能去掉引用的const。不仅仅能去掉变量表达式的const也能去掉函数的const。

  最后,const_cast不能去掉变量的const。这是编程的安全基础。除const外,const_cast也能去掉volatile属性,和去掉const一样。

  reinterpret_cast:

  reinterpret_cast这种强制类型转换是一种非常强的强制类型转换,它可以将任何两个无关的指针或引用进行转换。上面的static_cast进行强制类型转换时,会进行编译时的类型安全检查,即你可以将int转换成float,将子类引用(指针)转换成父类引用(指针),子转父和父转子都可以,但父转子不安全。但是你不能使用static_cast将两个无关的东西的转换,比如两个无关类。

classB *p = &b;
classA *q = static_cast<ClassA &>(p);

  但如果使用的reinterpret_cast强制类型转换,就不会进行静态类型检查直接放行通过。

  dynamic_cast:

  前面我们介绍过了satice_cast,从名称上看,一个动(dynamic_cast)一个静(static_cast)肯定有关系。我们知道static_cast会在编译的过程中进行安全检查,而dynamic_cast会在运行的过程中进行安全性检查。这两个都带安全性检查可以防止错误的类型转换导致程序跑偏。

  dynamic_cast既然是动态安全性检查,那么它肯定只能应用于指针或引用,不能用于内置的数据类型转换(内置的数据类型转换,在编译阶段由static_cast检查即可)。dynamic_cast不但检查两个指针是否属于同一个继承树(static_cast也检查这个),还会检查这种转换是否可行。如果可行就会返回一个新指针,并计算出处理多继承的需要的必须的偏移量。如果不可行会返回NULL。因此即使我们使用reinterpret_cast强制类型转换骗过编译器编译成功,如果我们在使用前再使用dynamic_cast转换检测一下的话,还是能发现这个错误的转换的。

总结:

  1、static_cast会进行静态的安全检查,一般用于内置数据类型的转换和通常的类之间的转换

  2、const_cast主要是用来去掉指针和引用的const和volatile类型

  3、reinterpret_cast用于完全没有关系指针和引用之间的转换,比如字符指针转整型指针。

  4、dynamic_cast通常用于基类和派生类之间的相互转换。

posted @ 2018-11-14 23:04  daisy_ai  阅读(193)  评论(0编辑  收藏  举报