命名空間
變體
動作

運算式

出自 cppreference.com
< cpp‎ | language
 
 
C++ 語言
一般主題
流程控制
條件執行陳述式
if
疊代陳述式 (迴圈)
for
範圍 for (C++11)
跳躍陳述式
函式
函式宣告
Lambda 函式運算式
inline 指定符
動態例外規範 (直到 C++17*)
noexcept 指定符 (C++11)
例外
命名空間
型別
指定符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
儲存期指定符
初始化
 
 

運算式是運算子 (operators) 及其運算元 (operands) 的序列,用以指定一個計算。

運算式求值可能會產生結果(例如:對 2 + 2 求值會得到結果 4),也可能會產生副作用(例如:對 std::printf("%d", 4) 求值會將字元 '4' 列印至標準輸出)。

每個 C++ 運算式都有兩個獨立的屬性:類型 (type) 與值類別 (value category)。

目錄

[編輯] 概覽

  • 值類別(lvalue、rvalue、glvalue、prvalue、xvalue(C++11 起))根據運算式的值對其進行分類
  • 求值順序 指明引數與子運算式的計算順序,進而決定取得中間結果的順序

[編輯] 運算子

常用運算子
賦值 遞增
遞減
算術 邏輯 比較 成員
存取
其他

a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &&= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b

a[...]
*a
&a
a->b
a.b
a->*b
a.*b

函數呼叫

a(...)
逗號

a, b
條件

a ? b : c
特殊運算子

static_cast 將一種類型轉換為另一種相關類型
dynamic_cast 在繼承體系中進行轉換
const_cast 新增或移除 cv 限定符
reinterpret_cast 將類型轉換為不相關的類型
C 風格轉換 透過結合 static_castconst_castreinterpret_cast 將一種類型轉換為另一種類型
new 建立具有動態儲存期的物件
delete 銷毀先前由 new 運算式建立的物件並釋放取得的記憶體區域
sizeof 查詢類型的容量大小
sizeof... 查詢參數包的大小 (自 C++11 起)
typeid 查詢類型的類型資訊
noexcept 檢查運算式是否可能拋出例外 (自 C++11 起)
alignof 查詢類型的對齊要求 (自 C++11 起)

[編輯] 轉換

[編輯] 記憶體配置

[編輯] 其他

[編輯] 主要運算式

任何運算子的運算元可以是其他運算式或主要運算式(例如在 1 + 2 * 3 中,operator+ 的運算元為子運算式 2 * 3 與主要運算式 1)。

主要運算式包括以下任何一項:

(C++26 起)
(C++11 起)
(自 C++17 起)
(自 C++20 起)

任何括號中的運算式亦被歸類為主要運算式:這保證了括號具有高於任何運算子的優先級。括號會保留值、型別與值類別。

[編輯] 字面量

字面量是 C++ 程式中代表原始程式碼中嵌入的常量值的語彙單元 (tokens)。

  • charwchar_t
  • char16_tchar32_t
(C++11 起)
  • char8_t
(自 C++20 起)
  • const char[]const wchar_t[]
  • const char16_t[]const char32_t[]
(C++11 起)
  • const char8_t[]
(自 C++20 起)
(C++11 起)

[編輯] 完整運算式

組成運算式 (constituent expression) 定義如下:

  • 一個運算式的組成運算式即為該運算式本身。
  • 大括號括起的初始化列表或(可能帶括號的)運算式列表的組成運算式,是該列表各元素的組成運算式。
  • = 開頭的 初始化器 的組成運算式,是該 initializer-clause 的組成運算式。
int num1 = 0;
num1 += 1; // Case 1: the constituent expression of “num += 1” is “num += 1”
 
int arr2[2] = {2, 22} // Case 2: the constituent expressions
                      //         of “{2, 22}” are “2” and “22”
                      // Case 3: the constituent expressions of “= {2, 22}”
                      //         are the constituent expressions of “{2, 22}”
                      //         (i.e. also “2” and “22”)

運算式 E直接子運算式 (immediate subexpressions) 為:

  • E 之運算元的組成運算式,
(C++14 起)
  • Elambda 運算式,則為值捕獲實體的初始化以及捕獲初始化器的組成運算式,
(C++11 起)
  • E 隱式呼叫的任何函式呼叫,或
  • E 為函式呼叫或隱式呼叫函式,則為呼叫中所使用的每個 預設引數 的組成運算式。

運算式 E子運算式 (subexpression)E 的直接子運算式,或是 E 的直接子運算式的子運算式。注意,出現在 lambda 運算式「函式體」中的運算式並非該 lambda 運算式的子運算式。(C++11 起)

以下運算式為 完整運算式 (full-expressions)

(自 C++20 起)
(C++26 起)
  • 不屬於任何其他運算式的子運算式,且未作為任何完整運算式一部分的運算式

若語言構造被定義為產生對函式的隱式呼叫,則該語言構造的使用就本定義而言被視為一個運算式。為了滿足出現該運算式的語言構造的要求,而應用於運算結果的轉換也被視為完整運算式的一部分。

對於初始化器,執行實體的初始化 (包括對聚合的預設成員初始化器求值)(C++14 起) 也被視為完整運算式的一部分。

[編輯] 潛在求值運算式

運算式為 潛在求值 (potentially evaluated),除非:

  • 它是 sizeof 運算子的運算元,或
  • 它是 typeid 運算子的運算元,且不指定 多型 類別型別的 lvalue。
(直到 C++11)

以下運算元為 未求值運算元 (unevaluated operands),它們不會被求值:

  • typeid 運算子所作用的運算式(多型類別型別的 glvalue 除外)
  • sizeof 運算子的運算元
  • noexcept 運算子的運算元
  • decltype 指定符的運算元
(自 C++20 起)

運算式為 潛在求值 (potentially evaluated),除非:

  • 它是未求值運算元,或
  • 它是未求值運算元的子運算式。
(C++11 起)

潛在求值運算式屬於 ODR-use

[編輯] 丟棄值運算式

丟棄值運算式 (discarded-value expression) 是指僅因其副作用而使用的運算式。從這類運算式計算出的值會被丟棄。此類運算式包括任何 運算式語句 的完整運算式、內建逗號運算子的左運算元,或轉換為 void 型別的轉型運算式的運算元。

陣列轉指標與函式轉指標的轉換永遠不會應用於丟棄值運算式所計算的值。僅當運算式為 volatile 限定 的 glvalue 且具有以下形式之一(需為內建含義,可能帶括號)時,才會應用 lvalue 轉 rvalue 的轉換:

  • 識別符運算式 (id-expression),
  • 陣列下標運算式,
  • 類別成員存取運算式,
  • 間接運算 (indirection),
  • 指向成員指標運算,
  • 第二與第三運算元皆為上述運算式之一的條件運算式,
  • 右運算元為上述運算式之一的逗號運算式。

此外,若該 lvalue 為 volatile 限定的類別型別,則需要一個 volatile 複製建構函式來初始化所得的 rvalue 臨時物件。

若該運算式為非 void 的 prvalue(在經過任何可能發生的 lvalue 轉 rvalue 轉換後),則會發生 臨時物件具現化 (temporary materialization)

當表達式(轉換為 void 者除外)丟棄宣告為 [[nodiscard]] 的值時,編譯器可能會發出警告。

(自 C++17 起)

運算式等價性

若滿足以下所有條件,則多個運算式 e1, e2, ..., eN運算式等價 (expression-equivalent)

  1. 它們具有相同的效果。
  2. 它們要麼都是 常量子運算式,要麼都不是。
  3. 它們要麼都是 noexcept 的,要麼都不是。

若且唯若 e1e2 為運算式等價時(這意味著 e2 也與 e1 運算式等價),則稱 e1 運算式等價於 e2

(自 C++20 起)

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯應用於之前的 C++ 標準。

DR 應用於 出版時的行為 正確的行為
CWG 1054 C++98 賦值給 volatile 變數可能會
導致因 lvalue 轉
rvalue 轉換應用於賦值結果而產生不必要的讀取
引入丟棄值運算式
並將此情況從
需要該轉換的情況清單中排除
CWG 1343 C++98 聚合初始化中解構函式呼叫的
定序說明不足
聚合初始化中的完整運算式
已明確定義
CWG 1383 C++98 將 lvalue 轉 rvalue 轉換應用於
丟棄值運算式的運算式清單
也涵蓋了重載運算子
僅涵蓋
具有內建含義的運算子
CWG 1576 C++11 lvalue 轉 rvalue 轉換未應用於
丟棄值 volatile xvalue 運算式
應用此轉換
在此情況下
CWG 2249 C++98 將在宣告子中宣告的識別符
並非識別符運算式
它們是
CWG 2431 C++11 綁定到參考的臨時物件的
解構函式呼叫不是完整運算式
它們是

[編輯] 參見

C 語言文件 關於 運算式 的內容
English Deutsch 日本語 中文(简体) 中文(繁體)