问题
Small and pretty nasty problem I've seen several days ago, asked to my friend on interview.
The initial interview question was: "What will be the output of the following code?"
int i = 2;
i = i++ + i++;
The correct answer is ((2 + 2) + 1) + 1 = 6, i.e. post-increment is applied twice before assignment, but after addition.
Then I wanted to create a simple class carrying one integer and overload operator+() and operator++(int) to see in logs the exact order, in which operators will be executed.
This is what I got:
class A
{
public:
A(int _data) : data(_data) { }
A &operator=(const A& _rhs)
{
data = _rhs.data;
cout<<" -- assign: "<<data<<endl;
}
A operator++(int _unused)
{
A _tmp = data;
data++;
cout<<" -- post-increment: "<<data<<endl;
return _tmp;
}
A operator+(const A &_rhs)
{
A _tmp = data + _rhs.data;
cout<<" -- addition: "<<data<<"+"<<_rhs.data<<endl;
return _tmp;
}
inline operator int() const { return data; }
private:
int data;
};
The result was pretty discouraging:
-- post-increment: 3
-- post-increment: 4
-- addition: 3+2
-- assign: 5
For less sophisticated constructions, such as (A _dt2 = a++; ), it acts as it should, but the order of operators execution is not as for integral types.
It might be compiler specific problem, I guess:
$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
So, I'm a bit lost :)
回答1:
The initial interview question was: "What will be the output of the following code?"
int i = 2;
i = i++ + i++;
The correct answer is undefined behaviour, because you're modifying the same variable multiple times without a sequence point in between.
C++03 Standard §5 [expr] p4
:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.
This may not answer your real question, but it will be similar even if you make an integer-like class and overload the operator++(int)
and operator+(A const&)
. The order of evaluation of arguments to a function is unspecified, it may be done in any order the compiler likes, thus the result is unspecified.
回答2:
Aside from what others already pointed out: Taking the title of your question in isolation - "Create C++ integer class to act absolutely identical to integral integer type" - I should point out a completely different reason why it is impossible.
It is (to my knowledge) not possible to emulate the shortcut behaviour of the || and && operators with classes, i.e. both sides of the operand will be evaluated no matter what.
Edit: Check out the comments. "To my knowledge" appears to not have been enough. However, Steve Jessop has a different example that makes the overall point stand valid.
This is completely unrelated to your increment question, but topical to your question title, so I thought it should be mentioned.
回答3:
The correct answer is ((2 + 2) + 1) + 1 = 6, i.e. post-increment is applied twice before assignment, but after addition.
That is not the correct answer:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
- ISO-IEC-14882
回答4:
Actually, you made a pretty bad error early on.
The initial interview question was: "What will be the output of the following code?"
int i = 2;
i = i++ + i++;
The correct answer to this question is "The output is undefined."
By modifying and reading a variable without an interceding sequence point, you are invoking undefined behavior.
More specifically, in this case what bites you in the ass is that the order in which parameters to the +
operator are evaluated are undefined; and this is true in the general case of both operators and functions, with a few notable exceptions, namely short-circuiting logical operators.
来源:https://stackoverflow.com/questions/7914972/create-c-integer-class-to-act-absolutely-identical-to-integral-integer-type