运算符++的返回值

时间:2013-07-30 18:42:38

标签: c++

我有以下代码被破坏了。我可以通过修改代码中的某些行来修复它(请参阅注释)。问题的原因是什么?

#include <iostream>
using namespace std;

class Number{
public:
    int n;
    Number(int a):n(a){}

    //when I change the following to
    //friend Number& operator++(Number& source, int i)
    //then it compiles fine and correct value is printed
    friend Number operator++(Number& source, int i){
        ++source.n;
        return source;
    }
};

int main() {

    Number x(5);
    x++++; //error: no 'operator++(int)' declared for postfix '++' [-fpermissive]
    cout<<x.n;

    return 0;
}

4 个答案:

答案 0 :(得分:16)

您尝试将第二个++应用于第一次调用返回的临时对象。但是,操作数必须通过引用传递,并且您不能将临时绑定到非常量 lvalue 引用。

你可能不想“修复”这个,因为没有理由修改这样的临时值。但是,您应该在递增之前返回值的副本,以提供预期的增量后行为。

前缀运算符应返回一个引用,该引用可以愉快地绑定到另一个引用,以便++++x;按预期工作。

答案 1 :(得分:8)

您正在通过编写operator++来增加内部x++ ++的返回值。这意味着如果该运算符的返回值不是可修改的值,则代码将无法编译。

因此,如果您声明它返回Number而不是Number &,则无法修改它(函数的返回值是临时的而不是左值,除非它是引用,因此外部运算符++,它通过(非常量)引用获取它,不能将它绑定到由value返回的对象。

答案 2 :(得分:3)

你要做的事情很不寻常。后增量通常返回一个rvalue,表示对象之前增量(与预增量相反,后者首先递增对象,然后返回该对象本身,作为左值)。由于无法解释的原因,你基本上试图使后增量的行为与预增量相同。

通常,你会这样做:

class Number {
  int n;
public:
  // Pre-increment
  Number& operator++() {
    ++n;
    return *this;
  }
  Number operator++(int) {
    Number temp = *this;  // capture old value
    ++(*this);
    return temp;
  }
};

使用这个定义,x++++不会编译 - 但是当xint时它也不会编译:它实际上没有多大意义。

无论如何,它不适合你的原因如下。 x++++被解释为

operator++(operator++(x, 0), 0)

内部operator++调用返回临时Number对象。外部operator++()需要类型为Number&的参数 - 但非const引用不能绑定到临时引用。当您更改声明以便operator++返回Number& - 左值 - 时,此返回值可以愉快地传递到外部operator++调用。

答案 3 :(得分:0)

让我们首先观察你不能为int链接这样的postincrement运算符!

然后在我遇到问题之前,让我建议不要写这样的非直观的代码。从现在开始,有人必须在一年后阅读您的课程,并希望尽可能轻松地学习。

考虑x++++实际上类似于operator++(operator++(x, int), int)所以现在发生的事情是第一个operator++按值返回(导致返回未命名的临时值)。这个未命名的临时值不能绑定到第二个(外部)调用的非const引用参数,并且方法查找失败。

最后请注意,您的实现实际上并没有实现postfix增量:它实现了前缀增量。您应该删除int参数(表示postfix)或修复实现以返回未修改的值。