重载递减运算符时使用的额外参数是什么?
What is the extra argument used for when overloading the decrement operator?
当我重载 post-递减运算符时,我必须包含一个额外的参数:
#include <iostream>
template<class T>
class wrap
{
public:
bool operator >(T &&v)
{
return value > v;
}
T operator --(int v) // Remove 'int v' and you get a compilation error
{
return (value -= 1) + 1;
}
wrap(T v)
{
value = v;
}
private:
T value;
};
int main(void)
{
wrap<int> i(5);
while(i --> 0)
std::cout << "Why do we need the extra argument?\n";
return 0;
}
如果删除这个看似不需要的参数,则会出现编译错误:
test.cpp: In function ‘int main()’:
test.cpp:26:13: error: no ‘operator--(int)’ declared for postfix ‘--’ [-fpermissive]
while(i --> 0)
~~^~
这个参数有什么用?它的值代表什么?
因为您使用的是后缀递减:
while (i-- > 0)
应该减少 i
但 return 原始值:
T operator--(int) // dummy int param for postfix
{
T temp = value;
value -= 1;
return temp;
}
虚拟int
参数只是一个占位符,用于区分后缀和前缀递减:
T operator--() // no param for prefix
{
value -= 1;
return value;
}
来自cppreference:
The int
parameter is a dummy parameter used to differentiate between prefix and postfix versions of the operators. When the user-defined postfix operator is called, the value passed in that parameter is always zero, although it may be changed by calling the operator using function call notation (e.g., a.operator++(2)
or operator++(a, 2)
).
虽然我强烈建议不要围绕这些显式调用创建功能(对于其他任何人来说,这看起来会非常奇怪)。
operator++
- pre-increment and post-increment 有两个独立但相关的重载。两者都是可覆盖的。由于它们具有相同的名称,C++ 的设计者必须决定一种语法,让编译器区分它们。他们选择在 post 增量运算符上使用虚拟 int
参数。
当你这样写代码时:
wrap<int> i(5);
++i; // <-- calls i.operator++();
编译器发出代码来调用无参数 operator++()
。
当您编写这样的代码时:
wrap<int> i(5);
i++; // <-- calls i.operator++(0);
编译器发出代码来调用带参数的 operator++(int)
,为虚拟参数传递 0
。
参数的 value 没有意义,它的存在足以让 operator++
的每个重载被单独覆盖,因为它们具有不同的签名。
顺便说一句,同样的规则也适用于 pre/post-decrement operator--
。
每个已批准的 ANSI 和 ISO C++ 标准以及每个工作草案都对此进行了描述,尽管版本之间的精确措辞有所不同。
例如,根据 "Working Draft, Standard for Programming Language C++",文档编号 N4659,日期为 2017-03-21,第 16.5.7 节 "Increment and decrement [over.inc]",第 1 段
The user-defined function called operator++
implements the prefix and postfix ++
operator. If this function is a non-static member function with no parameters, or a non-member function with one parameter, it defines the prefix increment operator ++
for objects of that type. If the function is a non-static member function with one parameter (which shall be of type int) or a non-member function with two parameters (the second
of which shall be of type int), it defines the postfix increment operator ++
for objects of that type. When the postfix increment is called as a result of using the ++
operator, the int argument will have value zero.
在上一段的末尾,有对脚注 134 的引用,其中说
Calling operator++
explicitly, as in expressions like a.operator++(2)
, has no special properties: The argument to operator++
is 2
.
在第 1 段之后,标准甚至提供了示例。
[ Example:
struct X {
X& operator++(); // prefix ++a
X operator++(int); // postfix a++
};
struct Y { };
Y& operator++(Y&); // prefix ++b
Y operator++(Y&, int); // postfix b++
void f(X a, Y b) {
++a; // a.operator++();
a++; // a.operator++(0);
++b; // operator++(b);
b++; // operator++(b, 0);
a.operator++(); // explicit call: like ++a;
a.operator++(0); // explicit call: like a++;
operator++(b); // explicit call: like ++b;
operator++(b, 0); // explicit call: like b++;
}
— end example ]
第2段接着说
The prefix and postfix decrement operators --
are handled analogously.
当我重载 post-递减运算符时,我必须包含一个额外的参数:
#include <iostream>
template<class T>
class wrap
{
public:
bool operator >(T &&v)
{
return value > v;
}
T operator --(int v) // Remove 'int v' and you get a compilation error
{
return (value -= 1) + 1;
}
wrap(T v)
{
value = v;
}
private:
T value;
};
int main(void)
{
wrap<int> i(5);
while(i --> 0)
std::cout << "Why do we need the extra argument?\n";
return 0;
}
如果删除这个看似不需要的参数,则会出现编译错误:
test.cpp: In function ‘int main()’: test.cpp:26:13: error: no ‘operator--(int)’ declared for postfix ‘--’ [-fpermissive] while(i --> 0) ~~^~
这个参数有什么用?它的值代表什么?
因为您使用的是后缀递减:
while (i-- > 0)
应该减少 i
但 return 原始值:
T operator--(int) // dummy int param for postfix
{
T temp = value;
value -= 1;
return temp;
}
虚拟int
参数只是一个占位符,用于区分后缀和前缀递减:
T operator--() // no param for prefix
{
value -= 1;
return value;
}
来自cppreference:
The
int
parameter is a dummy parameter used to differentiate between prefix and postfix versions of the operators. When the user-defined postfix operator is called, the value passed in that parameter is always zero, although it may be changed by calling the operator using function call notation (e.g.,a.operator++(2)
oroperator++(a, 2)
).
虽然我强烈建议不要围绕这些显式调用创建功能(对于其他任何人来说,这看起来会非常奇怪)。
operator++
- pre-increment and post-increment 有两个独立但相关的重载。两者都是可覆盖的。由于它们具有相同的名称,C++ 的设计者必须决定一种语法,让编译器区分它们。他们选择在 post 增量运算符上使用虚拟 int
参数。
当你这样写代码时:
wrap<int> i(5);
++i; // <-- calls i.operator++();
编译器发出代码来调用无参数 operator++()
。
当您编写这样的代码时:
wrap<int> i(5);
i++; // <-- calls i.operator++(0);
编译器发出代码来调用带参数的 operator++(int)
,为虚拟参数传递 0
。
参数的 value 没有意义,它的存在足以让 operator++
的每个重载被单独覆盖,因为它们具有不同的签名。
顺便说一句,同样的规则也适用于 pre/post-decrement operator--
。
每个已批准的 ANSI 和 ISO C++ 标准以及每个工作草案都对此进行了描述,尽管版本之间的精确措辞有所不同。
例如,根据 "Working Draft, Standard for Programming Language C++",文档编号 N4659,日期为 2017-03-21,第 16.5.7 节 "Increment and decrement [over.inc]",第 1 段
The user-defined function called
operator++
implements the prefix and postfix++
operator. If this function is a non-static member function with no parameters, or a non-member function with one parameter, it defines the prefix increment operator++
for objects of that type. If the function is a non-static member function with one parameter (which shall be of type int) or a non-member function with two parameters (the second of which shall be of type int), it defines the postfix increment operator++
for objects of that type. When the postfix increment is called as a result of using the++
operator, the int argument will have value zero.
在上一段的末尾,有对脚注 134 的引用,其中说
Calling
operator++
explicitly, as in expressions likea.operator++(2)
, has no special properties: The argument tooperator++
is2
.
在第 1 段之后,标准甚至提供了示例。
[ Example:
struct X { X& operator++(); // prefix ++a X operator++(int); // postfix a++ }; struct Y { }; Y& operator++(Y&); // prefix ++b Y operator++(Y&, int); // postfix b++ void f(X a, Y b) { ++a; // a.operator++(); a++; // a.operator++(0); ++b; // operator++(b); b++; // operator++(b, 0); a.operator++(); // explicit call: like ++a; a.operator++(0); // explicit call: like a++; operator++(b); // explicit call: like ++b; operator++(b, 0); // explicit call: like b++; }
— end example ]
第2段接着说
The prefix and postfix decrement operators
--
are handled analogously.