递增/递减运算符
递增/递减运算符会递增或递减对象的 value。
运算符名称 | 语法 | 可重载 | 原型示例(对于 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&) |
||
[编辑] 后缀运算符
后缀增量和减量表达式具有以下形式
表达式 ++ |
|||||||||
表达式 -- |
|||||||||
[编辑] 内置后缀运算符
后缀增量或减量的结果是 表达式 在修改之前的 prvalue 复制。结果的类型是 表达式 类型的不带 cv 限定符的版本。
如果 表达式 不是算术类型的可修改左值,除了(可能是具有 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--,即使这些运算符对于特定迭代器是无操作的。
算术类型的重载 | |
将原子值增量或减量 1 ( std::atomic<T> 的公共成员函数) | |
将滴答计数增量或减量 ( std::chrono::duration<Rep,Period> 的公共成员函数) | |
迭代器类型的重载 | |
使迭代器前进 ( std::raw_storage_iterator<OutputIt,T> 的公共成员函数) | |
使迭代器前进或后退 ( std::reverse_iterator<Iter> 的公共成员函数) | |
使迭代器前进或后退 ( std::move_iterator<Iter> 的公共成员函数) | |
无操作 ( std::front_insert_iterator<Container> 的公共成员函数) | |
无操作 ( std::back_insert_iterator<Container> 的公共成员函数) | |
无操作 ( std::insert_iterator<Container> 的公共成员函数) | |
使迭代器前进 ( std::istream_iterator<T,CharT,Traits,Distance> 的公共成员函数) | |
无操作 ( std::ostream_iterator<T,CharT,Traits> 的公共成员函数) | |
使迭代器前进 ( std::istreambuf_iterator<CharT,Traits> 的公共成员函数) | |
无操作 ( std::ostreambuf_iterator<CharT,Traits> 的公共成员函数) | |
使迭代器前进到下一个匹配项 ( std::regex_iterator<BidirIt,CharT,Traits> 的公共成员函数) | |
使迭代器前进到下一个子匹配项 ( std::regex_token_iterator<BidirIt,CharT,Traits> 的公有成员函数) |
[编辑] 错误报告
以下行为变更错误报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布的行为 | 正确行为 |
---|---|---|---|
CWG 2855 | C++98 | 对前置递增和 前置递减应用了通常的算术转换,但没有应用于其后置对应项[1] |
也应用 |
- ↑ 前置 ++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 文档 针对 递增/递减运算符
|