8

为什么 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 ??
}
4

6 回答 6

8

不,重载的运算符不是运算符 - 它们是函数。所以GCC接受这一点是正确的。

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

于 2011-07-14T10:53:53.880 回答
3

因为对于用户定义的类型,运算符重载实际上只是函数调用,因此遵守函数调用的语义。

于 2011-07-14T10:54:37.580 回答
2

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

MyInt const operator++(int) { … }

几年前,关于用户定义的运算符是否应该准确地模拟内置行为存在争论。我不确定目前哪个学派占上风,但将返回类型operator++(int) const设为 是实现这一目标的一种方式。

于 2011-07-14T15:03:38.917 回答
1

最后,MyInt::operator++(int)只是另一种方法。相同的规则适用。由于您可以在右值上调用方法,因此您可以在右值operator++(int)上调用。

于 2011-07-14T10:56:47.623 回答
1

myint++ 返回类似于 MyInt(2) 的内容。因此,它类似于执行 MyInt(2)++。在 operator++ 函数中创建了一个临时类,并且您正在递增临时类。返回后,一旦下一条语句完成,它就会被删除(这里是第二个 ++ 运算符)。

于 2011-07-14T11:00:26.737 回答
1

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

如果您已将运算符实现为自由函数:

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

那么该特定运营商的要求将是从实际签名中提取的要求。如果第一个参数是按值获取的,那么它直接接受右值,如果它接受参数,const &那么如果复制构造函数可访问,则它接受右值,如果参数是非常量,&那么该运算符将需要左值。

于 2011-07-14T11:27:40.753 回答