自增/自减运算符
自增/自减运算符递增或递减对象的值。
运算符名称 | 语法 | 可重载 | 原型示例 (对于 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 起) |
[编辑] 重载
在针对用户定义运算符的重载决议中,对于每个可选地带有 volatile 限定的算术类型 A
(除了 bool)以及对于每个可选地带有 volatile 限定的指针 P
,指向可选地带有 cv 限定的对象类型,以下函数签名参与重载决议
A& operator++(A&) |
||
bool& operator++(bool&) |
(已弃用)(直至 C++17) | |
P& operator++(P&) |
||
A& operator--(A&) |
||
P& operator--(P&) |
||
[编辑] 后缀运算符
后缀自增和自减表达式具有以下形式
表达式 ++ |
|||||||||
表达式 -- |
|||||||||
[编辑] 内置后缀运算符
后缀自增或自减的结果是通过将左值到右值转换应用于 表达式 (在修改之前)而获得的值。结果的类型是 表达式 类型的非 cv 限定版本。
如果 表达式 不是算术类型的可修改左值 (除了(可能带 cv 限定的) bool之外)(自 C++17 起),或者指向完整对象类型的指针,则程序为非良构。
如果 表达式 的类型是 volatile 限定的,则自增或自减已被弃用。 |
(自 C++20 起) |
++
运算符的操作数一样。--
运算符的操作数一样。后缀自增或自减的值计算先于 表达式 的修改进行。关于不确定顺序的函数调用,后缀自增或自减的操作是单次求值。
[编辑] 重载
在针对用户定义运算符的重载决议中,对于每个可选地带有 volatile 限定的算术类型 A
(除了 bool)以及对于每个可选地带有 volatile 限定的指针 P
,指向可选地带有 cv 限定的对象类型,以下函数签名参与重载决议
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> 的公共成员函数) | |
递增或递减嘀嗒计数 ( std::chrono::duration<Rep,Period> 的公共成员函数) | |
迭代器类型的重载 | |
推进迭代器 ( std::raw_storage_iterator<OutputIt,T> 的公共成员函数) | |
推进或递减 reverse_iterator ( std::reverse_iterator<Iter> 的公共成员函数) | |
推进或递减 move_iterator ( 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] |
也已应用 |
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 文档 关于 自增/自减运算符
|