Create C++ integer class to act absolutely identical to integral integer type

牧云@^-^@ 提交于 2021-01-27 03:56:13

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!