他们是两个独立的运营商,因为他们做两件不同(尽管相关)的事情。
预递增/递减将递增/递减变量并返回新值。
int i = 0;
int j = ++i; // j is now 1
后递增/递减将递增/递减变量并返回旧值。
int i = 0;
int j = i++; // j is now 0
通常,这些运算符的实现如下所示(对于某些类型T
):
T& T::operator++() // prefix overload
{
*this = *this + 1;
return *this;
}
T T::operator++(int) // postfix overload
{
T prev = *this;
++(*this); // call prefix overload
return prev;
}
如您所见,前缀重载不需要类型的额外副本,而后缀版本则需要。
由于大部分评论都围绕着为什么会这样的问题:
简短的回答是:因为 C 标准是这样说的(并且 C++ 从 C 继承了它)。
更长的答案是:
++a
并且a++
只是调用特定函数的简写符号。 ++a
(对于给定的类型T
)映射到T& T::operator++()
orT& operator++(T&)
并且a++
映射到T T::operator++(int)
or T operator(T&, int)
。与所有运算符一样,您(作为程序员)可以将它们定义为针对相应类型执行任何您想做的事情(注意:通常认为重载运算符来做一些奇怪的事情是不好的做法,但标准不会阻止您这样做)。一般来说,如果您定义一个类型(例如迭代器),您可以通过提供类似的接口(例如重载适当的运算符)使其与内置类型(例如指针)的行为相匹配。但是,你可以决定你想要operator++()
执行二次公式并operator++(int)
进行傅里叶变换。因为它们是 2 个独立的功能,所以这是允许的。operator++(int)
如果允许编译器基于将根据 定义的前提进行推断operator++()
,则它们将绑定在一起。
C++ 中的运算符只不过是函数调用的简写符号。虽然根据其他运算符来实现多个运算符是很常见的,但标准并不要求这样做,因此编译器无法做出这样的假设。如果标准要求它,那么就会有很多假设的行为需要跟踪。
此外,++a
and的行为a++
是 C 的继承。存在许多利用其中一种行为的代码,并且在 C++ 标准中更改它会破坏与 C 的兼容性(除非您还制作了C标准的变化)。由于有许多现有代码利用了这些运算符的行为,因此您可能会做出重大的重大更改。
虽然在前增量方面实现后增量是很常见的,但您确实应该将这两个函数视为不同的函数(与您对operator==
vs operator!=
、operator<
、operator>
等的想法非常相似。仅仅因为某些东西很常见并不意味着该标准将甚至应该将其作为一项要求。