c++-运算

算术运算符

运算符功能
+ (单目)
- (单目)
* (双目)乘法
/除法
%取模
+ (双目)加法
- (双目)减法

单目与双目运算符

算术运算符中有两个单目运算符(正、负)以及五个双目运算符(乘法、除法、取模、加法、减法),其中单目运算符的优先级最高.

其中取模运算符 % 意为计算两个整数相除得到的余数,即求余数.

而 - 为双目运算符时做减法运算符,如 2-1 ;为单目运算符时做负值运算符,如 -1 .

使用方法如下

op=x-y*z

得到的 op 的运算值遵循数学中加减乘除的优先规律,首先进行优先级高的运算,同优先级按运算的结合性运算,括号提高优先级.

算术运算中的类型转换

对于双目算术运算符,当参与运算的两个变量类型相同时,不发生 类型转换,运算结果将会用参与运算的变量的类型容纳,否则会发生类型转换,以使两个变量的类型一致.转换的规则参见 类型转换

例如,对于一个整型(int)变量 𝑥�

 和另一个双精度浮点型(double)类型变量 𝑦�

  • x/3 的结果将会是整型;
  • x/3.0 的结果将会是双精度浮点型;
  • x/y 的结果将会是双精度浮点型;
  • x*1/3 的结果将会是整型;
  • x*1.0/3 的结果将会是双精度浮点型;

位操作符

另请参阅:位运算

运算符功能
~逐位非
& (双目)逐位与
|逐位或
^逐位异或
<<逐位左移
>>逐位右移

位操作的意义请参考 位操作 页面.需要注意的是,位操作的优先级低于算术运算符(除了取反),而按位与、按位或及异或低于比较运算符(详见 C++ 运算符优先级总表),所以使用时需多加注意,在必要时添加括号.

移位运算中如果出现如下情况,则其行为未定义:

  1. 右操作数(即移位数)为负值;
  2. 右操作数大于等于左操作数的位数;

例如,对于 int32_t 类型的变量 aa<<-1 和 a<<32 都是未定义的.

对于带符号非负数的左移操作,需要确保移位后的结果能被原数的类型容纳,否则行为也是未定义的.1对一个负数执行左移操作也未定义.2

对于右移操作,右侧多余的位将会被舍弃,而左侧较为复杂:对于无符号数,会在左侧补 00

3;而对于有符号数,则会用最高位的数(其实就是符号位,非负数为 00

,负数为 11

)补齐4

自增/自减 运算符

有时我们需要让变量进行增加 1(自增)或者减少 1(自减),这时自增运算符 ++ 和自减运算符 -- 就派上用场了.

自增/自减运算符可放在变量前或变量后面,在变量前称为前缀,在变量后称为后缀,单独使用时前缀后缀无需特别区别,如果需要用到表达式的值则需注意,具体可看下面的例子.详细情况可参考 引用 介绍的例子部分.

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
i = 100; op1 = i++; // op1 = 100,先 op1 = i,然后 i = i + 1 i = 100; op2 = ++i; // op2 = 101,先 i = i + 1,然后赋值 op2 i = 100; op3 = i--; // op3 = 100,先赋值 op3,然后 i = i - 1 i = 100; op4 = --i; // op4 = 99,先 i = i - 1,然后赋值 op4 

复合赋值运算符

复合赋值运算符实际上是表达式的缩写形式.可分为复合算术运算符 +=-=*=/=%= 和复合位操作符 &=|=^=<<=>>=

例如,op = op + 2 可写为 op += 2op = op - 2 可写为 op -= 2op= op * 2 可写为 op *= 2

条件运算符

条件运算符可以看作 if 语句的简写,a ? b : c 中如果表达式 a 成立,那么这个条件表达式的结果是 b,否则条件表达式的结果是 c

比较运算符

运算符功能
>大于
>=大于等于
<小于
<=小于等于
==等于
!=不等于

其中特别需要注意的是要将等于运算符 == 和赋值运算符 = 区分开来,这在判断语句中尤为重要.

if (op=1) 与 if (op==1) 看起来类似,但实际功能却相差甚远.第一条语句是在对 op 进行赋值,若赋值为非 0 时为真值,表达式的条件始终是满足的,无法达到判断的作用;而第二条语句才是对 op 的值进行判断.

逻辑运算符

运算符功能
&&逻辑与
||逻辑或
!逻辑非

1 2 3 4 5
Result = op1 && op2; // 当 op1 与 op2 都为真时则 Result 为真 Result = op1 || op2; // 当 op1 或 op2 其中一个为真时则 Result 为真 Result = !op1; // 当 op1 为假时则 Result 为真 

内建的运算符 && 和 || 进行短路求值(若在求值第一个操作数后结果已知,则不求值第二个),重载的运算符无此特性,并始终对两个操作数都进行求值.

逗号运算符

逗号运算符可将多个表达式分隔开来,被分隔开的表达式按从左至右的顺序依次计算,整个表达式的值是最后的表达式的值.逗号表达式的优先级在所有运算符中的优先级是 最低 的.

 1 2 3 4 5 6 7 8 9 10
exp1, exp2, exp3; // 最后的值为 exp3 的运算结果. Result = 1 + 2, 3 + 4, 5 + 6; //得到 Result 的值为 3 而不是 11,因为赋值运算符 "=" //的优先级比逗号运算符高,先进行了赋值运算才进行逗号运算. Result = (1 + 2, 3 + 4, 5 + 6); // 若要让 Result 的值得到逗号运算的结果则应将整个表达式用括号提高优先级,此时 // Result 的值才为 11. 

成员访问运算符

运算符功能
[]数组下标
.对象成员
& (单目)取地址/获取引用
* (单目)间接寻址/解引用
->指针成员

这些运算符用来访问对象的成员或者内存,除了最后一个运算符外上述运算符都可被重载.与 & , * 和 -> 相关的内容请阅读 指针 和 引用 教程.这里还省略了两个很少用到的运算符 .* 和 ->* ,其具体用法可以参见 C++ 语言手册 .

1 2 3 4 5
auto result1 = v[1]; // 获取v中下标为2的对象 auto result2 = p.q; // 获取p对象的q成员 auto result3 = p -> q; // 获取p指针指向的对象的q成员,等价于 (*p).q auto result4 = &v; // 获取指向v的指针 auto result5 = *v; // 获取v指针指向的对象 

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_caststatic_castdynamic_castreinterpret_casttypeidsizeof...noexcept 及 alignof 等运算符,因为它们的使用形式与函数调用相同,不会出现歧义.

参考资料与注释


  1. C++20 前.C++20 起的行为参见1. 
  2. 即 逻辑右移. 

即 算术右移.C++20 前,带符号的右移是依实现定义的,在大多数实现中,均采用算术右移.C++20 起,规定 a >> b 为 ⌊𝑎/2𝑏⌋⌊�/2�⌋

,所以带符号数右移运算是算术右移

C++20 前,若原值为带符号类型,且移位后的结果能被原类型的无符号版本容纳,则将该结果 转换 为相应的带符号值,否则行为未定义;无符号数的左移则舍弃移出结果类型的位.C++20 起,规定 a << b 为 𝑎 ⋅2𝑏�⋅2�

 在模 2𝑁2�

 下的值(𝑁�

 为结果类型的位宽),即无论是带符号数还是无符号数,左移均直接舍弃移出结果类型的位(即 算术左移/逻辑左移). 

Read more

C++短信通知接口示例代码:高性能C++发送通知短信的接口实现及调用逻辑

C++短信通知接口示例代码:高性能C++发送通知短信的接口实现及调用逻辑

在后端开发场景中,短信通知是系统触达用户的核心能力之一,而基于C++开发的高性能服务,对短信接口的调用效率、稳定性要求更高。本文将聚焦c++短信通知接口API示例代码,从底层调用逻辑拆解、实战代码实现、异常处理等维度,手把手教你实现高性能的C++短信通知接口调用,解决开发者在对接短信接口时遇到的参数配置、请求异常、性能优化等核心痛点。 一、C++短信通知接口调用核心原理拆解 1.1 短信接口调用的基本流程 C++调用短信通知接口本质是通过HTTP协议与短信服务商的服务端建立通信,完成参数传递与响应接收,核心流程可分为4步: 1. 构建符合接口规范的HTTP请求(包含请求头、核心参数); 2. 建立网络连接,发送请求到短信接口地址; 3. 接收服务端响应数据并解析; 4. 根据响应结果处理成功/失败逻辑,完成重试或日志记录。 1.2 高性能调用的关键设计要点 C++作为编译型语言,实现高性能短信接口调用需关注两个核心: * 网络请求层面:使用异步非阻塞IO(如libcurl的multi接口)避免主线程阻塞; * 数据处理层面:

By Ne0inhk
【C++:继承】C++面向对象继承全面解析:派生类构造、多继承、菱形虚拟继承与设计模式实践

【C++:继承】C++面向对象继承全面解析:派生类构造、多继承、菱形虚拟继承与设计模式实践

🔥艾莉丝努力练剑:个人主页 ❄专栏传送门:《C语言》、《数据结构与算法》、C/C++干货分享&学习过程记录、Linux操作系统编程详解、笔试/面试常见算法:从基础到进阶 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬艾莉丝的简介: 🎬艾莉丝的C++专栏简介: 目录 C++的两个参考文档 4  ~>  派生类的默认成员函数专题 4.4  实现一个不可继承类实现 4.4.1  间接实现:【C++98】构造函数私有的类不能被继承 4.4.2  直接实现:final关键字修改基类 4.4.3  代码实现 4.4.4  final关键字

By Ne0inhk

C/C++ static关键字详解(最全解析,static是什么,static如何使用,static的常考面试题)

C/C++ static 关键字最全详解(2026版) 小白到高手、笔试到面试一次讲透! 一、一句话核心总结 static 是“让变量/函数的生命周期或可见范围改变”的关键字,它有三种完全不同的含义,取决于用在什么位置**: 1. 改变存储期(让局部变量变成“全局寿命”) 2. 改变链接性(让全局变量/函数“只在本文件可见”) 3. 属于类而非对象(类静态成员) 记不住全部也没关系,记住这三句话就够日常和面试用了: * 局部 static = “函数内永生变量” * 全局 static = “本文件私有变量/函数” * 类 static = “全类共享成员” 二、static 的三种核心用法对比表(背这个表就够了) 用法位置C语言支持C++支持含义生命周期可见范围默认初始化值局部静态变量YesYes存储期变为静态(函数结束后不销毁)整个程序本函数0全局静态变量YesYes链接性变为内部链接整个程序本文件0全局静态函数YesYes链接性变为内部链接(不可被其他文件调用)整个程序本文件-类静态成员变量NoYes属于类,

By Ne0inhk