简体   繁体   中英

Why does the postfix increment operator take a dummy parameter?

Have a look at these function signatures:

 class Number {
 public:
   Number& operator++ ();    // prefix ++
   Number  operator++ (int); // postfix ++
 }; 

Prefix doesn't take any parameter but postfix does. Why? I thought we can recognize them with different return types.

Prefix and postfix ++ are different operators. With the standard Foo operator symbol(Foo &) style declaration there was no obvious way to distinguish the two. Rather than come up with some new syntax like Foo symbol operator(Foo &) which would make it into a special case unlike all the other operators and likely a bit of a pain to parse, the language designers wanted some other solution.

The solution they chose was somewhat bizarre. They noted that all the other 'postfix' operators (ie operators that occurred after one of their operands) were actually infix operators that took two arguments. For example, plain old + , / or > . On this basis the language designers decided that having a random dummy argument would be a good way to distinguish between prefix and postfix ++ .

IMHO, it's one of the stranger decisions made as C++ evolved. But there you have it.

And you can't distinguish them based on return type for two reasons.

The first is that functions in C++ cannot be overloaded on return type. You cannot have two functions that have identical names and parameter type lists but different return values.

The second is that method would not be robust or flexible enough to handle all possible implementations of prefix and postfix ++ .

For example, you might want a postfix ++ that returned a reference type if the only reason you ever called it was to invoke a side-effect unrelated to the value of the variable you were applying it to. In my opinion, that would be a very bad implementation, but C++ is not about judging what kinds of stupid code you want to write, but about enabling you to write whatever code it is you think appropriate to the situation. And forcing you to use one particular style of return type for prefix ++ and postfix ++ would be contrary to that spirit.

You are free to give operator++ any return type you like, so there's not way to distinguish postfix and prefix by that. So the compiler needs some kind of clue.

OTOH, I don't know why this couldn't had been done in syntax only:

//prefix
int& ++operator (); 
//postfix
int& operator++ (); 

After all, mimicking usage in declarations has tradition in C and C++.

PS Other posters: This has nothing to do with overloading by return type. postfix and prefix ++/-- are two different names. There is no need to resolve an overload in x++ or ++x , because it's entirely clear which name is meant.

Straight from Bjarne's mouth:

This may be both too cute and too subtle, but it works, requires no new syntax, and has a logic to the madness. Other unary operators are prefix and take no arguments when defined as member functions. The "odd" and unused dummy int argument is used to indicate the odd postfix operators. In other words, in the postfix case, ++ comes between the first (real) operand and the second (dummy) argument and is thus postfix.

These explanations are needed because the mechanism is unique and therefore a bit of a wart. Given a choice, I would probably have introduced the prefix and postfix keywords, but that didn't appear feasible at the time. However, the only really important point is that the mechanism works and can be understood and used by the few programmers who really need it.

By the way, in my opinion, only prefix ++ should be overloadable by the programmer, and postfix ++ should be automatically generated by the compiler. Does anyone agree with me?

您不允许纯粹通过返回类型重载函数,因此需要一个虚拟参数来区分两个相同的operator++()运算符。

The compiler uses the int argument to distinguish between the prefix and postfix increment operators. For implicit calls, the default value is zero so actully it does not make so much difference in functionality of overloaded operator...

If I had my druthers, postincrement and many sequence-point operators would be split into two or three parts; in the case of postincrement, a statement like "a=(b++ + c++);" would be effectively translated as "a=postinc1(b)+postinc1(c); postinc2(b); postinc2(c);"; the second part of post-increment would be a void function. In actual implementation, the postinc2() calls should often likely occur while some other results are sitting on the evaluation stack; that shouldn't be too hard for a compiler to implement.

In the case of "&&" or "||", the first part of the operator would just operate on the left operand; if it returned non-zero (for &&) or non-zero (for ||), then the second part would operate on both operands.

In the case of "?"/":", the first part of the operator would operate on just the first operand. If it returned non-zero, the second part would operate on the first and second parameters; otherwise the third part would operate on the first and third parameters.

Do any languages do anything like that? It seems odd that C++ allows operators to be redefined in ways that break sequencing behavior, but does not allow them to be redefined in ways that preserve it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM