Зачем нужна ссылка при перегрузке оператора? - PullRequest
0 голосов
/ 16 февраля 2020

В каких ситуациях при перегрузке понадобится ссылка, поскольку код все еще работает без нее? Я знаю, что это связано с цепочкой, но я точно не понимаю, зачем нужна ссылка.

Пример:

Object& operator++();

Ответы [ 4 ]

3 голосов
/ 16 февраля 2020

Без «ссылки» операторская функция вернет значением - и это будет копия исходного объекта - что не является тем, что предназначено.

Например, попробуйте следующий код с использованием и без использования «ссылки», и вы увидите различные результаты последнего вызова 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.

2 голосов
/ 16 февраля 2020

Встроенный унарный оператор ++ возвращает ссылку на объект, для которого применяется оператор.

Например, вы можете написать

int i = 10;
++++i;

Так имитировать то же поведение Определяемые пользователем операторы также должны возвращать ссылку на объект.

0 голосов
/ 16 февраля 2020

Давайте рассмотрим ваш пример - мы можем захотеть увеличить один и тот же объект в два раза, поэтому мы можем sh сделать следующее:

#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

Если мы должны вернуть объект, а не ссылку на this , тогда мы оперируем l -значение ссылки (поскольку у этого объекта нет имени!), следовательно, эта цепочка не сделает ничего с исходным объектом, как можно видеть в следующем примере:

#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
0 голосов
/ 16 февраля 2020

Так что вы можете написать что-то вроде: x = i++; Я не думаю, что это необходимо; он просто используется таким образом в общем, и это может вызвать проблему в коде, который предполагает, что оператор возвращает значение / ссылку - в этом случае вы не сможете использовать свой объект в этом коде, если он не возвращает соответствующее значение , Кроме того, другие программисты могут счесть ваш код вводящим в заблуждение, если операторы делают странные вещи, которых они не ожидают.

Примечание: некоторые типы возвращают копию объекта вместо ссылки: i++ (копия старого val) vs ++i (новое значение).

...