表示式
表示式是**運算子**及其**運算元**的序列,它指定了計算。
表示式求值可能會產生結果(例如,2 + 2 的求值產生結果 4),並可能產生副作用(例如,std::printf("%d", 4) 的求值會在標準輸出上列印字元 '4')。
每個 C++ 表示式都由兩個獨立的屬性來表徵:型別和值類別。
目錄 |
[編輯] 概述
[編輯] 運算子
| 常見運算子 | ||||||
|---|---|---|---|---|---|---|
| 賦值 | 遞增 遞減 |
算術 | 邏輯 | 比較 | 成員 訪問 |
其他 |
|
a = b |
++a |
+a |
!a |
a == b |
a[...] |
函式呼叫 a(...) |
| 逗號 a, b | ||||||
| 條件 a ? b : c | ||||||
| 特殊運算子 | ||||||
|
static_cast 將一種型別轉換為另一種相關型別 | ||||||
[編輯] 轉換
- 標準轉換 從一種型別到另一種型別的隱式轉換
-
const_cast轉換 -
static_cast轉換 -
dynamic_cast轉換 -
reinterpret_cast轉換 - 顯式轉換 使用 C 風格轉換符號和函式風格符號的轉換
- 使用者定義轉換 使得指定從使用者定義類進行的轉換成為可能
[編輯] 記憶體分配
- new 表示式 動態分配記憶體
- delete 表示式 動態釋放記憶體
[編輯] 其他
- 常量表達式 可以在編譯時求值,並用於編譯時上下文(模板引數、陣列大小等)
-
sizeof -
alignof -
typeid - 丟擲表示式 (throw-expression)
[編輯] 主表示式
任何運算子的運算元可以是其他表示式或主表示式(例如,在 1 + 2 * 3 中,運算子 + 的運算元是子表示式 2 * 3 和主表示式 1)。
主表示式是以下任何一種
-
this - 字面量(例如 2 或 "Hello, world")
- 識別符號表示式,包括
- 適當宣告的非限定識別符號(例如 n 或 cout),
- 適當宣告的限定識別符號(例如 std::string::npos),以及
- 宣告符中待宣告的識別符號
| (C++26 起) |
| (C++11 起) | |
| (C++17 起) | |
| (C++20 起) |
任何括號中的表示式也被歸類為主表示式:這保證了括號的優先順序高於任何運算子。括號保留值、型別和值類別。
[編輯] 字面量
字面量是 C++ 程式中表示嵌入在原始碼中的常量值的標記。
- char 或 wchar_t
|
(C++11 起) |
|
(C++20 起) |
- const char[] 或 const wchar_t[]
|
(C++11 起) |
|
(C++20 起) |
- 布林字面量 是 bool 型別的值,即 true 和 false
| (C++11 起) |
[編輯] 完整表示式
**組成表示式**定義如下
- 表示式的組成表示式就是該表示式。
- 大括號括起來的初始化列表或(可能帶括號的)表示式列表的組成表示式是各自列表元素的組成表示式。
- 以
=開頭的初始化器的組成表示式是 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 的**直接子表示式**是
- E 的運算元的組成表示式,
| (C++14 起) | |
|
(C++11 起) |
- E 隱式呼叫的任何函式呼叫,或
- 如果 E 是函式呼叫或隱式呼叫函式,則是在呼叫中使用的每個預設實參的組成表示式。
表示式 E 的**子表示式**是 E 的直接子表示式,或 E 的直接子表示式的子表示式。請注意,出現在 lambda 表示式“函式體”中的表示式不是 lambda 表示式的子表示式。(C++11 起)
以下表達式是**完整表示式**
| (C++20 起) |
|
(C++26 起) |
- 不是任何其他表示式的子表示式且不以其他方式作為任何完整表示式的一部分的表示式
如果一個語言構造被定義為產生一個函式的隱式呼叫,則該語言構造的使用被認為是為此定義目的的表示式。為了滿足表示式所在的語言構造的要求而應用於表示式結果的轉換也被認為是完整表示式的一部分。
對於一個初始化器,執行實體的初始化(包括對聚合的預設成員初始化器的求值)(C++14 起)也被認為是完整表示式的一部分。
[編輯] 潛在求值表示式
|
一個表示式是**潛在求值**的,除非 |
(C++11 前) | ||
|
以下運算元是**未求值運算元**,它們不被求值
一個表示式是**潛在求值**的,除非
|
(C++11 起) |
潛在求值表示式是ODR 使用。
| 本節不完整 原因:未求值運算元的例子 |
[編輯] 丟棄值表示式
**丟棄值表示式**是僅用於其副作用的表示式。從此類表示式計算出的值將被丟棄。此類表示式包括任何表示式語句的完整表示式、內建逗號運算子的左運算元,或轉換為 void 型別的轉型表示式的運算元。
陣列到指標和函式到指標的轉換從不應用於丟棄值表示式計算的值。當且僅當表示式是 volatile 限定的泛左值並具有以下形式之一(要求內建含義,可能帶括號)時,才應用左值到右值的轉換
- id-expression,
- 陣列下標表達式,
- 類成員訪問表示式,
- 解引用,
- 指向成員的運算,
- 條件表示式,其中第二個和第三個運算元都是這些表示式之一,
- 逗號表示式,其中右運算元是這些表示式之一。
此外,如果左值是 volatile 限定的類型別,則需要 volatile 複製建構函式來初始化結果的右值臨時物件。
|
如果表示式是(在可能發生的任何左值到右值轉換之後)非 void 純右值,則發生臨時實體化。 當表示式(除轉換為 void 的表示式外)丟棄宣告為 |
(C++17 起) |
表示式等價多個表示式 e1、e2、...、eN 是**表示式等價**的,如果所有以下條件都滿足 e1 **表示式等價於** e2 當且僅當 e1 和 e2 表示式等價(這意味著 e2 也表示式等價於 e1)。 |
(C++20 起) |
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
| 缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
|---|---|---|---|
| CWG 1054 | C++98 | 給 volatile 變數賦值可能會 由於應用於賦值結果的左值到 右值轉換導致不必要的讀取 |
引入丟棄值表示式 並將此情況從要求轉換的 情況列表中排除 |
| CWG 1343 | C++98 | 聚合初始化中解構函式呼叫的 排序未明確指定 |
聚合初始化中的完整表示式 被明確指定 |
| CWG 1383 | C++98 | 左值到右值轉換應用於 丟棄值表示式的列表也包括 過載運算子 |
只包括具有內建含義的 運算子 |
| CWG 1576 | C++11 | 左值到右值轉換未應用於 丟棄值 volatile 將亡值表示式 |
應用轉換 在這種情況下 |
| CWG 2249 | C++98 | 宣告符中待宣告的識別符號 不是 id-expression |
它們是 |
| CWG 2431 | C++11 | 繫結到引用的臨時物件的解構函式 呼叫不是完整表示式 |
它們是 |
[編輯] 參閱
| C 文件 關於 表示式
|