跳转至

運算

算術運算符

運算符 功能
+ (單目)
- (單目)
* (雙目) 乘法
/ 除法
% 取模
+ (雙目) 加法
- (雙目) 減法
單目與雙目運算符

單目運算符(又稱一元運算符)指被操作對象只有一個的運算符,而雙目運算符(又稱二元運算符)的被操作對象有兩個。例如 1 + 2 中加號就是雙目運算符,它有 12 兩個被操作數。此外 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 的結果將會是雙精度浮點型;

位運算符

運算符 功能
~ 逐位非
& (雙目) 逐位與
| 逐位或
^ 逐位異或
<< 逐位左移
>> 逐位右移

位操作的意義請參考 位運算 頁面。需要注意的是,位運算符的優先級低於普通的算數運算符。

自增/自減 運算符

有時我們需要讓變量進行增加 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...noexceptalignof 等運算符,因為它們的使用形式與函數調用相同,不會出現歧義。