为什么 myClassObj++++ 不会产生编译错误:"++"需要 l 值,就像内置类型一样?

Why myClassObj++++ doesn't incur a compile error : '++' needs l-value just as buildin type do?

本文关键字:内置 置类型 一样 myClassObj++++ 编译 需要 错误 为什么      更新时间:2023-10-16

为什么myint++++编译好VS2008编译器和gcc 3.42编译器?我期望编译器说需要左值,示例如下。

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 ??
}

不,重载的操作符不是操作符——它们是函数。所以GCC是可以接受的

myobj++++;等价于myobj.operator++(0).operator++(0);允许在类类型的临时对象上调用成员函数(包括重载操作符)。

因为对于用户定义类型,操作符重载实际上只是函数调用,因此服从函数调用的语义。

如果你想模拟内置行为,实际上有一个非常简单的解决方案:使返回值const:

MyInt const operator++(int) { … }

几年前,有一个关于用户定义操作符是否应该完全模拟内置行为的争论。我不确定目前哪个学派占了上风,但是使operator++(int)的返回类型const是实现这一目标的一种方法。

最后,MyInt::operator++(int)只是另一种方法。同样的规则也适用。因为你可以在右值上调用方法,所以你可以在右值上调用operator++(int)

myint++返回类似于myint(2)的值。这和MyInt(2)++很相似。在operator++函数中创建了一个临时类,您正在对临时类进行加1操作。返回后,在下一条语句结束时(这里是第二个++操作符),它将被删除。

问题是整型和用户定义类型的后增量运算符的要求是不同的。特别是,用户定义的后增量运算符实现为成员函数,允许使用右值。

如果您将操作符实现为自由函数:

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

则该特定操作符的需求将是从实际签名中提取的需求。如果第一个实参被value接受,则直接接受右值;如果实参被const &接受,则在复制构造函数可访问的情况下接受右值;如果实参被非常量&接受,则该操作符将需要左值。