遞增/遞減運算子
遞增/遞減運算子用於增加或減少物件的值。
運算子名稱 | 語法 | 可過載 | 原型示例(對於 class T) | |
---|---|---|---|---|
類定義內部 | 類定義外部 | |||
前置遞增 | ++a
|
是 | T& T::operator++(); | T& operator++(T& a); |
前置遞減 | --a
|
是 | T& T::operator--(); | T& operator--(T& a); |
後置遞增 | a++
|
是 | T T::operator++(int); | T operator++(T& a, int); |
後置遞減 | a--
|
是 | T T::operator--(int); | T operator--(T& a, int); |
|
目錄 |
[編輯] 字首運算子
字首遞增和遞減表示式的形式為
++ 表示式 |
|||||||||
-- 表示式 |
|||||||||
[編輯] 內建字首運算子
|
(C++17 前) |
|
(C++17 起) |
|
(C++20 起) |
- 如果 表示式 的型別是 (可能帶有 cv 限定的) bool,則程式格式錯誤。
|
(C++20 起) |
[編輯] 過載
在針對使用者定義運算子的過載決議中,對於除 bool 之外的每個可選 volatile 限定的算術型別 A
,以及每個可選 cv 限定的物件型別的可選 volatile 限定指標 P
,以下函式簽名參與過載決議
A& operator++(A&) |
||
bool& operator++(bool&) |
(已棄用)(直到 C++17) | |
P& operator++(P&) |
||
A& operator--(A&) |
||
P& operator--(P&) |
||
[編輯] 字尾運算子
字尾遞增和遞減表示式的形式為
表示式 ++ |
|||||||||
表示式 -- |
|||||||||
[編輯] 內建字尾運算子
字尾遞增或遞減的結果是透過對 表示式 應用左值到右值轉換(在修改之前)獲得的值。結果的型別是 表示式 型別的 cv-unqualified 版本。
如果 表示式 不是算術型別(除可能 cv 限定的 bool 之外)(C++17 起) 的可修改左值,也不是指向完整物件型別的指標,則程式格式錯誤。
如果 表示式 的型別是 volatile 限定的,則遞增或遞減已被棄用。 |
(C++20 起) |
++
運算子的運算元一樣。--
運算子的運算元一樣。字尾遞增或遞減的值計算在 表示式 的修改之前排序。相對於不確定排序的函式呼叫,字尾遞增或遞減的操作是單個求值。
[編輯] 過載
在針對使用者定義運算子的過載決議中,對於除 bool 之外的每個可選 volatile 限定的算術型別 A
,以及每個可選 cv 限定的物件型別的可選 volatile 限定指標 P
,以下函式簽名參與過載決議
A operator++(A&, int) |
||
bool operator++(bool&, int) |
(已棄用)(直到 C++17) | |
P operator++(P&, int) |
||
A operator--(A&, int) |
||
P operator--(P&, int) |
||
[編輯] 示例
#include <iostream> int main() { int n1 = 1; int n2 = ++n1; int n3 = ++ ++n1; int n4 = n1++; // int n5 = n1++ ++; // error // int n6 = n1 + ++n1; // undefined behavior std::cout << "n1 = " << n1 << '\n' << "n2 = " << n2 << '\n' << "n3 = " << n3 << '\n' << "n4 = " << n4 << '\n'; }
輸出
n1 = 5 n2 = 2 n3 = 4 n4 = 4
[編輯] 注意
由於涉及副作用,內建遞增和遞減運算子必須小心使用,以避免由於違反排序規則而導致未定義行為。
由於在後置遞增和後置遞減期間會構造物件的臨時副本,因此在不使用返回值的上下文中,前置遞增或前置遞減運算子通常更高效。
[編輯] 標準庫
遞增和遞減運算子為許多標準庫型別過載。特別是,每個LegacyIterator都過載了 operator++,每個LegacyBidirectionalIterator都過載了 operator--,即使這些運算子對於特定的迭代器是空操作。
算術型別的過載 | |
將原子值遞增或遞減一 ( std::atomic<T> 的 public 成員函式) | |
增加或減少刻度計數 ( std::chrono::duration<Rep,Period> 的 public 成員函式) | |
迭代器型別的過載 | |
前進迭代器 ( std::raw_storage_iterator<OutputIt,T> 的 public 成員函式) | |
遞增或遞減 reverse_iterator ( std::reverse_iterator<Iter> 的 public 成員函式) | |
遞增或遞減 move_iterator ( std::move_iterator<Iter> 的 public 成員函式) | |
無操作 ( std::front_insert_iterator<Container> 的 public 成員函式) | |
無操作 ( std::back_insert_iterator<Container> 的 public 成員函式) | |
無操作 ( std::insert_iterator<Container> 的 public 成員函式) | |
前進迭代器 ( std::istream_iterator<T,CharT,Traits,Distance> 的 public 成員函式) | |
無操作 ( std::ostream_iterator<T,CharT,Traits> 的 public 成員函式) | |
前進迭代器 ( std::istreambuf_iterator<CharT,Traits> 的 public 成員函式) | |
無操作 ( std::ostreambuf_iterator<CharT,Traits> 的 public 成員函式) | |
將迭代器推進到下一個匹配項 ( std::regex_iterator<BidirIt,CharT,Traits> 的 public 成員函式) | |
將迭代器推進到下一個子匹配項 ( std::regex_token_iterator<BidirIt,CharT,Traits> 的 public 成員函式) |
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
CWG 2855 | C++98 | 通常的算術轉換應用於內建前置遞增和 前置遞減,但未應用於其後綴對應項[1] |
也已應用 |
CWG 2901 | C++98 | 左值到右值轉換未應用於 內建字尾遞增和字尾遞減 |
已應用 |
- ↑ 字首 ++x 等價於 x += 1,後者適用於通常的算術轉換(即在 decltype(x) 和 int 之間產生一個共同型別)。然而,字尾 x++ 的效果僅僅是“給 x 加一”,不存在二元運算子,因此不會發生通常的算術轉換。
[編輯] 參見
常見運算子 | ||||||
---|---|---|---|---|---|---|
賦值 | 遞增 遞減 |
算術 | 邏輯 | 比較 | 成員 訪問 |
其他 |
a = b |
++a |
+a |
!a |
a == b |
a[...] |
函式呼叫 a(...) |
逗號 a, b | ||||||
條件運算子 a ? b : c | ||||||
特殊運算子 | ||||||
static_cast 將一種型別轉換為另一種相關型別 |
C 文件 用於 遞增/遞減運算子
|