递增/递减运算符
递增/递减运算符用于增加或减少对象的值。
运算符名称 | 语法 | 可重载 | 原型示例(对于 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 文档 用于 递增/递减运算符
|