遞增/遞減運算子
遞增/遞減運算子用於增加或減少物件的值。
| 運算子名稱 | 語法 | 可過載 | 原型示例(對於 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 文件 用於 遞增/遞減運算子
|