为什么运算符重载需要引用?

Why is a reference needed in operator overloading?

在什么情况下重载时需要引用,因为没有它代码仍然有效?我知道它与链接有关,但我不明白为什么需要引用。

示例:

Object& operator++();

如果没有 'reference',运算符函数将 return by value - 这将是一个 copy 原始对象 - 这不是预期的。

例如,在使用和不使用 'reference' 的情况下尝试以下代码,您将看到最终 one.show() 调用的不同结果:

#include <iostream>

class myInt {
private:
    int value;
public:
    myInt() : value{ 0 } { }
    myInt(int x) : value{ x } { }
//    myInt operator ++() { ++value; return *this; }
    myInt& operator ++() { ++value; return *this; }
    void show() {
        std::cout << value << std::endl;
    }
};

int main(int argc, char* argv[])
{
    myInt one(1);
    one.show();
    myInt two = ++(++one);
    two.show();
    one.show(); // Difference shows here!
    return 0;
}

这是因为,在没有引用的情况下,括号外的 ++one 对象的本地创建的 copy 进行操作。

内置一元运算符 ++ return是对应用该运算符的对象的引用。

例如你可以这样写

int i = 10;
++++i;

因此,要模拟相同的行为,用户定义的运算符也应该 return 对象的引用。

所以你可以这样写:x = i++;我认为不需要它;它通常只是以这种方式使用,它可能会导致假设运算符 return 和 value/reference 的代码出现问题 - 在这种情况下,如果它,您将无法在该代码中使用您的对象return 没有合适的值。此外,如果操作员做出他们不期望的奇怪事情,其他程序员可能会发现您的代码具有误导性。

注意:某些类型 return 对象的副本而不是引用:i++(旧 val 的副本)与 ++i(新值)。

让我们看看您的示例 - 我们可能希望将同一对象增加两次,因此,我们可能希望执行以下操作:

#include <iostream>

class MyObject
{
    public:

    MyObject()
    {
        cnt = 0;
    }

    MyObject& operator++()
    {
        ++cnt;
        return *this;
    }

    int cnt;
};

int main()
{
  MyObject obj{};
  std::cout << "The value at start " << obj.cnt << std::endl;
  ++obj;
  std::cout << "The value after increment " << obj.cnt << std::endl;

  ++(++obj); // Legal ONLY when returning a reference!
  std::cout << "The value after two increments in the same time: " << obj.cnt << std::endl;
}

在这种情况下,我们使用链接将计数器增加两次,正如我们预期的那样,我们得到以下结果:

The value at start 0
The value after increment 1
The value after two increments in the same time: 3

如果我们应该 return 一个对象而不是对 this 的引用,那么,我们对左值引用进行操作(因为这个对象没有一个名字!),因此,此链接将对原始对象无任何作用,如以下示例所示:

#include <iostream>

class MyObject
{
    public:

    MyObject()
    {
        cnt = 0;
    }

    MyObject(const MyObject& other)
    {
        this->cnt = other.cnt;
    }

    MyObject operator++()
    {
        MyObject tmp(*this);

        ++cnt;

        return tmp;
    }

    int cnt;
};

int main()
{
  MyObject obj{};
  std::cout << "The value at start " << obj.cnt << std::endl;
  ++obj;
  std::cout << "The value after increment " << obj.cnt << std::endl;

  ++(++obj); // Legal ONLY when returning a reference!
  std::cout << "The value after two increments in the same time: " << obj.cnt << std::endl;
}

输出:

The value at start 0
The value after increment 1
The value after two increments in the same time: 2