Why myClassObj++++ doesn't incur a compile err

2019-04-22 20:48发布

Why myint++++ compiles fine with VS2008 compiler and gcc 3.42 compiler ?? I was expecting compiler say need lvalue, example see below.

struct MyInt
{
    MyInt(int i):m_i(i){}

    MyInt& operator++() //return reference,  return a lvalue
    {
        m_i += 1;
        return *this;
    }

    //operator++ need it's operand to be a modifiable lvalue
    MyInt operator++(int)//return a copy,  return a rvalue
    {
        MyInt tem(*this);
        ++(*this);
        return tem;
    }

    int     m_i;
};

int main()
{
    //control: the buildin type int
    int i(0);
    ++++i;  //compile ok
    //i++++; //compile error :'++' needs l-value, this is expected

    //compare 
    MyInt  myint(1);
    ++++myint;//compile ok
    myint++++;//expecting compiler say need lvalue , but compiled fine !? why ??
}

6条回答
Anthone
2楼-- · 2019-04-22 20:53

No, overloaded operators are not operators - they're functions. So GCC is correct to accept that.

myobj++++; is equivalent to myobj.operator++(0).operator++(0); Caling a member function (including overloaded operator) on a temprorary object of class type is allowed.

查看更多
smile是对你的礼貌
3楼-- · 2019-04-22 20:53

myint++ returns something similar to MyInt(2). So, it's similar to doing MyInt(2)++. A temporary class is created in the operator++ function and you're incrementing the temporary class. After it's returned, it's deleted as soon as the next statement finishes (here, it's second ++ operator).

查看更多
来,给爷笑一个
4楼-- · 2019-04-22 21:02

Because for user-defined types, operator overloads are literally just function calls, and so obey the semantics of function calls.

查看更多
萌系小妹纸
5楼-- · 2019-04-22 21:09

The issue is that the requirements of the postincrement operator for integral types and for user defined types are different. In particular a user defined postincrement operator implemented as a member function allow the use of rvalues.

If you had implemented the operator as a free function:

MyInt operator++(MyInt [const][&] x, int)

Then the requirements of that particular operator would be those extracted from the actual signature. If the first argument is taken by value, then it accepts rvalues directly, if it takes the argument by const & then it accepts rvalues if the copy constructor is accessible, if the argument is taken by non constant & then that operator will require lvalues.

查看更多
做自己的国王
6楼-- · 2019-04-22 21:11

If you want to emulate the built-in behaviour there’s actually a very simple solution: make the return value const:

MyInt const operator++(int) { … }

A few years back there was a debate over whether user-defined operators should exactly model the built-in behaviour. I’m not sure which school of thought currently has the upper hand, but making the return type of operator++(int) const was a way of achieving this.

查看更多
别忘想泡老子
7楼-- · 2019-04-22 21:18

In the end, MyInt::operator++(int) is just another method. The same rules apply. Since you can call methods on rvalues, you can call operator++(int) on rvalues.

查看更多
登录 后发表回答