运算
算术运算符
| 运算符 | 功能 |
|---|---|
+ (单目) | 正 |
- (单目) | 负 |
* (双目) | 乘法 |
/ | 除法 |
% | 取模 |
+ (双目) | 加法 |
- (双目) | 减法 |
单目与双目运算符
单目运算符(又称一元运算符)指被操作对象只有一个的运算符,而双目运算符(又称二元运算符)的被操作对象有两个.例如 1 + 2 中加号就是双目运算符,它有 1 和 2 两个被操作数.此外 C++ 中还有唯一的一个三目运算符 ?: .
算术运算符中有两个单目运算符(正、负)以及五个双目运算符(乘法、除法、取模、加法、减法),其中单目运算符的优先级最高.
其中取模运算符 % 意为计算两个整数相除得到的余数,即求余数.
而 - 为双目运算符时做减法运算符,如 2-1 ;为单目运算符时做负值运算符,如 -1 .
使用方法如下
op=x-y*z
得到的 op 的运算值遵循数学中加减乘除的优先规律,首先进行优先级高的运算,同优先级按运算的结合性运算,括号提高优先级.
算术运算中的类型转换
对于双目算术运算符,当参与运算的两个变量类型相同时,不发生 类型转换,运算结果将会用参与运算的变量的类型容纳,否则会发生类型转换,以使两个变量的类型一致.转换的规则参见 类型转换.
例如,对于一个整型(int)变量 𝑥x 和另一个双精度浮点型(
double)类型变量 𝑦y:
x/3的结果将会是整型;x/3.0的结果将会是双精度浮点型;x/y的结果将会是双精度浮点型;x*1/3的结果将会是整型;x*1.0/3的结果将会是双精度浮点型;
位操作符
另请参阅:位运算.
| 运算符 | 功能 |
|---|---|
~ | 逐位非 |
& (双目) | 逐位与 |
|| 逐位或 ^| 逐位异或 <<| 逐位左移 >>| 逐位右移
位操作的意义请参考 位操作 页面.需要注意的是,位操作的优先级低于算术运算符(除了取反),而按位与、按位或及异或低于比较运算符(详见 C++ 运算符优先级总表),所以使用时需多加注意,在必要时添加括号.
移位运算中如果出现如下情况,则其行为未定义:
- 右操作数(即移位数)为负值;
- 右操作数大于等于左操作数的位数;
例如,对于 int32_t 类型的变量 a,a<<-1 和 a<<32 都是未定义的.
对于带符号非负数的左移操作,需要确保移位后的结果能被原数的类型容纳,否则行为也是未定义的.1对一个负数执行左移操作也未定义.2
对于右移操作,右侧多余的位将会被舍弃,而左侧较为复杂:对于无符号数,会在左侧补 003;而对于有符号数,则会用最高位的数(其实就是符号位,非负数为 00
,负数为 11
)补齐4.
自增/自减 运算符
有时我们需要让变量进行增加 1(自增)或者减少 1(自减),这时自增运算符 ++ 和自减运算符 -- 就派上用场了.
自增/自减运算符可放在变量前或变量后面,在变量前称为前缀,在变量后称为后缀,单独使用时前缀后缀无需特别区别,如果需要用到表达式的值则需注意,具体可看下面的例子.详细情况可参考 引用 介绍的例子部分.
---|---
## 复合赋值运算符
复合赋值运算符实际上是表达式的缩写形式.可分为复合算术运算符 `+=`、`-=`、`*=`、`/=`、`%=` 和复合位操作符 `&=`、`|=`、`^=`、`<<=`、`>>=`.
例如,`op = op + 2` 可写为 `op += 2`,`op = op - 2` 可写为 `op -= 2`,`op= op * 2` 可写为 `op *= 2`.
## 条件运算符
条件运算符可以看作 `if` 语句的简写,`a ? b : c` 中如果表达式 `a` 成立,那么这个条件表达式的结果是 `b`,否则条件表达式的结果是 `c`.
## 比较运算符
运算符| 功能
---|---
`>`| 大于
`>=`| 大于等于
`<`| 小于
`<=`| 小于等于
`==`| 等于
`!=`| 不等于
其中特别需要注意的是要将等于运算符 `==` 和赋值运算符 `=` 区分开来,这在判断语句中尤为重要.
`if (op=1)` 与 `if (op==1)` 看起来类似,但实际功能却相差甚远.第一条语句是在对 op 进行赋值,若赋值为非 0 时为真值,表达式的条件始终是满足的,无法达到判断的作用;而第二条语句才是对 `op` 的值进行判断.
## 逻辑运算符
运算符| 功能
---|---
`&&`| 逻辑与
`||`| 逻辑或
`!`| 逻辑非
---|---
内建的 运算符 && 和 || 进行短路求值(若在求值第一个操作数后结果已知,则不求值第二个),重载的运算符无此特性,并始终对两个操作数都进行求值.
逗号运算符
逗号运算符可将多个表达式分隔开来,被分隔开的表达式按从左至右的顺序依次计算,整个表达式的值是最后的表达式的值.逗号表达式的优先级在所有运算符中的优先级是 最低 的.
---|---
## 成员访问运算符
运算符| 功能
---|---
`[]`| 数组下标
`.`| 对象成员
`&` (单目)| 取地址/获取引用
`*` (单目)| 间接寻址/解引用
`->`| 指针成员
这些运算符用来访问对象的成员或者内存,除了最后一个运算符外上述运算符都可被重载.与 `&` , `*` 和 `->` 相关的内容请阅读 [指针](../pointer/) 和 [引用](../reference/) 教程.这里还省略了两个很少用到的运算符 `.*` 和 `->*` ,其具体用法可以参见 [C++ 语言手册](https://zh.cppreference.com/w/cpp/language/operator_member_access) .
---|---
C++ 运算符优先级总表
来自 C++ 运算符优先级 - cppreference ,有修改.
| 运算符 | 描述 | 例子 | 可重载性 |
|---|---|---|---|
| 第一级别 | |||
:: | 作用域解析符 | Class::age = 2; | 不可重载 |
| 第二级别 | |||
++ | 后自增运算符 | for (int i = 0; i < 10; i++) cout << i; | 可重载 |
-- | 后自减运算符 | for (int i = 10; i > 0; i--) cout << i; | 可重载 |
type() type{} | 强制类型转换 | unsigned int a = unsigned(3.14); | 可重载 |
() | 函数调用 | isdigit('1') | 可重载 |
[] | 数组数据获取 | array[4] = 2; | 可重载 |
. | 对象型成员调用 | obj.age = 34; | 不可重载 |
-> | 指针型成员调用 | ptr->age = 34; | 可重载 |
| 第三级别 (从右向左结合) | |||
++ | 前自增运算符 | for (i = 0; i < 10; ++i) cout << i; | 可重载 |
-- | 前自减运算符 | for (i = 10; i > 0; --i) cout << i; | 可重载 |
+ | 正号 | int i = +1; | 可重载 |
- | 负号 | int i = -1; | 可重载 |
! | 逻辑取反 | if (!done) … | 可重载 |
~ | 按位取反 | flags = ~flags; | 可重载 |
(type) | C 风格强制类型转换 | int i = (int) floatNum; | 可重载 |
* | 指针取值 | int data = *intPtr; | 可重载 |
& | 值取指针 | int *intPtr = &data | 可重载 |
sizeof | 返回类型内存 | int size = sizeof floatNum; int size = sizeof(float); | 不可重载 |
new | 动态元素内存分配 | long pVar = new long; MyClass ptr = new MyClass(args); | 可重载 |
new [] | 动态数组内存分配 | long *array = new long[n]; | 可重载 |
delete | 动态析构元素内存 | delete pVar; | 可重载 |
delete [] | 动态析构数组内存 | delete [] array; | 可重载 |
| 第四级别 | |||
.* | 类对象成员引用 | obj.*var = 24; | 不可重载 |
->* | 类指针成员引用 | ptr->*var = 24; | 可重载 |
| 第五级别 | |||
* | 乘法 | int i = 2 * 4; | 可重载 |
/ | 除法 | float f = 10.0 / 3.0; | 可重载 |
% | 取余数(模运算) | int rem = 4 % 3; | 可重载 |
| 第六级别 | |||
+ | 加法 | int i = 2 + 3; | 可重载 |
- | 减法 | int i = 5 - 1; | 可重载 |
| 第七级别 | |||
<< | 位左移 | int flags = 33 << 1; | 可重载 |
>> | 位右移 | int flags = 33 >> 1; | 可重载 |
| 第八级别 | |||
<=> | 三路比较运算符 | if ((i <=> 42) < 0) ... | 可重载 |
| 第九级别 | |||
< | 小于 | if (i < 42) ... | 可重载 |
<= | 小于等于 | if (i <= 42) ... | 可重载 |
> | 大于 | if (i > 42) ... | 可重载 |
>= | 大于等于 | if (i >= 42) ... | 可重载 |
| 第十级别 | |||
== | 等于 | if (i == 42) ... | 可重载 |
!= | 不等于 | if (i != 42) ... | 可重载 |
| 第十一级别 | |||
& | 位与运算 | flags = flags & 42; | 可重载 |
| 第十二级别 | |||
^ | 位异或运算 | flags = flags ^ 42; | 可重载 |
| 第十三级别 |
|| 位或运算| flags = flags | 42;| 可重载 第十四级别| | | &&| 逻辑与运算| if (conditionA && conditionB) ...| 可重载 第十五级别| | | ||| 逻辑或运算| if (conditionA || conditionB) ...| 可重载 第十六级别 (从右向左结合)| | | ? :| 条件运算符| int i = a > b ? a : b;| 不可重载 throw| 异常抛出| throw EClass("Message");| 不可重载 =| 赋值| int a = b;| 可重载 +=| 加赋值运算| a += 3;| 可重载 -=| 减赋值运算| b -= 4;| 可重载 =| 乘赋值运算| a = 5;| 可重载 /=| 除赋值运算| a /= 2;| 可重载 %=| 模赋值运算| a %= 3;| 可重载 <<=| 位左移赋值运算| flags <<= 2;| 可重载 >>=| 位右移赋值运算| flags >>= 2;| 可重载 &=| 位与赋值运算| flags &= new_flags;| 可重载 ^=| 位异或赋值运算| flags ^= new_flags;| 可重载 |=| 位或赋值运算| flags |= new_flags;| 可重载 第十七级别| | | ,| 逗号分隔符| for (i = 0, j = 0; i < 10; i++, j++) ...| 可重载
需要注意的是,表中并未列出 const_cast、static_cast、dynamic_cast、reinterpret_cast、typeid、sizeof...、noexcept 及 alignof 等运算符,因为它们的使用形式与函数调用相同,不会出现歧义.
参考资料与注释
- C++20 前,若原值为带符号类型,且移位后的结果能被原类型的无符号版本容纳,则将该结果 转换 为相应的带符号值,否则行为未定义;无符号数的左移则舍弃移出结果类型的位.C++20 起,规定
a << b为 𝑎 ⋅2𝑏a⋅2b在模 2𝑁2N
下的值(𝑁N
为结果类型的位宽),即无论是带符号数还是无符号数,左移均直接舍弃移出结果类型的位(即 算术左移/逻辑左移). ↩↩
- C++20 前.C++20 起的行为参见1. ↩
- 即 逻辑右移. ↩
- 即 算术右移.C++20 前,带符号的右移是依实现定义的,在大多数实现中,均采用算术右移.C++20 起,规定
a >> b为 ⌊𝑎/2𝑏⌋⌊a/2b⌋,所以带符号数右移运算是算术右移. ↩
本页面最近更新: 2026/1/27 12:26:08,更新历史 发现错误?想一起完善?在 GitHub 上编辑此页! 本页面贡献者:ouuan, cmpute, StudyingFather, Enter-tainer, Xeonacid, aofall, H-J-Granger, mgt, countercurrent-time, NachtgeistW, Ir1d, Marcythm, sshwy, Tiphereth-A, AngelKitty, CCXXXI, cjsoft, diauweb, Early0v0, ezoixx130, GekkaSaori, Konano, LovelyBuggies, Makkiy, minghu6, P-Y-Y, PotassiumWings, SamZhangQingChuan, Suyun514, weiyong1024, billchenchina, c-forrest, GavinZhengOI, Gesrua, greyqz, hhc0001, kxccc, leonfyr, Link-cute, lychees, Ocautator, Peanut-Tang, Shen-Linwood, shuzhouliu, SukkaW, TOMWT-qwq, yusancky 本页面的全部内容在CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用