<C++学习十五>C++运算符
摘要: 本篇博客仅作为笔记,如有侵权,请联系,立即删除(网上找博客学习,然后手记笔记,因纸质笔记不便保存,所以保存到网络笔记)
运算符是一种告诉编译器执行特定的数字或逻辑操作的符号。C++内置了丰富的运算符,并提供了以下类型的运算符:
算术运算符 关系运算符 逻辑运算符
位运算符 赋值运算符 杂项运算符
1、算术运算符
运算符 | 描述 |
+ | 把两个操作数相加 |
- | 从第一个操作数中减去第二个操作数 |
* | 把两个操作数相乘 |
/ | 分子除以分母 |
% | 取模运算符,整除后的余数 |
++ | 自增运算符,整数值增加1 |
-- | 自减运算符,整数值减少1 |
2、关系运算符
运算符 | 描述 |
== | 检查两个操作数的值是否相等,如果相等则条件为真 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真 |
< | 检查左操作数的值是否小于右操作数,如果是则条件为真 |
>= | 检查左操作数的值是否大于等于右操作数的值,如果是则条件为真 |
<= | 检查左操作数的值是否小于等于右操作数的值,如果是则条件为真 |
3、逻辑运算符
运算符 | 描述 |
&& | 称为逻辑与运算符。如果两个操作数都非零,则条件为真 |
|| | 称为逻辑或运算。如果两个操作数中有任意一个非零,则条件为真 |
! | 称为逻辑非运算符,用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假 |
4、赋值运算符
运算符 | 描述 |
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 |
<<= | 左移且赋值运算符 |
=>> | 右移且赋值运算符 |
&= | 按位与且赋值运算符 |
^= | 按位异或且赋值运算符 |
!= | 按位或且赋值运算符 |
5、位运算符
运算符 | 描述 |
& | 如果同时存在于两个操作数中,二进制AND运算符复制一位到结果中 |
| | 如果存在任一操作数中,而精致款OR运算符复制一位到结果中 |
^ | 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中 |
~ | 二进制补码运算符是一元运算符,具有“翻转”位效果,即0变成1,1变成0 |
<< | 二进制左移运算符,左操作数向左移动右操作数指定的位数 |
>> | 二进制右移运算符,左操作数向右移动右操作数指定的位数 |
6、杂项运算符
运算符 | 描述 |
sieof | sieof运算符返回变量的大小 |
condition?x:y | 条件运算符 |
, | 逗号运算符会执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值 |
. / -> | 成员运算符用于引用类、结构和共用体的成员 |
cast | 强制转换类型运算符把一种数据类型转换成另一种数据类型。 |
& | 指针运算符&返回变量地址 |
* | 指针运算符*指向一个变量 |
关于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通常用于基类和派生类之间的相互转换。