Функция-член класса C++ со ссылочным возвращаемым типом

Я новичок в программировании и C++. Я смущен тем, как здесь ссылка работает по-другому.

Код ниже выводит 0 5, но удаление & из A &GotObj() приведет к выводу 0 0. Почему во втором случае не выводится 0 5?

Заранее спасибо.

#include <iostream>
using namespace std;

class A {
public:
    int val;
    A(int n=0) {
        val = n;

    }
    A &GetObj() {
        return *this;
    }
};

int main() {
    A a;
    cout << a.val << endl;
    a.GetObj() = 5;
    cout << a.val << endl;
    return 0;
}

person Wesley    schedule 07.01.2016    source источник
comment
Просто был серьезный момент wtf, пока я не пометил c'tor как явный.   -  person StoryTeller - Unslander Monica    schedule 07.01.2016


Ответы (3)


Случай 1: GetObj()

  • позволяет создать объект класса A:

A a;

  • предположим, что расположение памяти этого объекта - 0x87965432. Теперь, когда вы вызываете функцию объекта a с помощью a.GetObj(), она возвращает временный объект, расположение памяти которого будет полностью отличаться от объекта a класса A, скажем, 0x98672345. >. теперь, если вы присвоите значение 5 с помощью

а.ПолучитьОбъект() = 5

  • то вы присваиваете значение 5 объекту, расположенному в ячейке памяти 0x98672345. теперь вы собираетесь напечатать переменную val объекта, расположенного в ячейке памяти 0x87965432. вот почему он будет печатать 0.

Случай 2: &GetObj()

  • как объяснено в случае 1, если вы создаете объект

A a;

  • давайте рассмотрим его расположение в памяти 0x87965432. теперь, когда вы вызываете функцию GetObj с помощью a.GetObj(), возвращаемый объект будет находиться в той же ячейке памяти 0x87965432, что и его концепция возврата по ссылке. теперь присваиваем этому объекту значение 5,

а.ПолучитьОбъект() = 5

будет отражать эффект в объекте a. и теперь печатаемое значение переменной val будет таким, как ожидалось 5.

person Nishant    schedule 07.01.2016
comment
Это на самом деле неправильно. C++ строго типизирован, вы не можете просто волей-неволей присваивать объекты без соответствующего оператора присваивания. - person StoryTeller - Unslander Monica; 07.01.2016
comment
@StoryTeller, если вы считаете, что память мудра, то есть только одна переменная val, тогда, назначив a.GetObj() = 5, она назначит 5 только val. - person Nishant; 07.01.2016
comment
Пока вы не добавите double участника, и ваше объяснение не исчезнет. Пока пример работает. - person StoryTeller - Unslander Monica; 07.01.2016
comment
да, в случае двойного члена на сцену выходит концепция строгого типа С++. однако для этого вопроса его достаточно, чтобы иметь смысл. - person Nishant; 07.01.2016
comment
@Nishant Ваш ответ Помогите мне :) - person Rajan; 07.01.2016
comment
@Nishant Большое спасибо! Думаю, теперь я понял. Возврат *this создает временный объект, местоположение которого отличается, но имеет то же значение val. - person Wesley; 08.01.2016

Когда вы возвращаете значение, выражение a.GetObj() просто создает временный. Назначение затем только изменяет значение этого временного.

person Cheers and hth. - Alf    schedule 07.01.2016

Это ссылка как просто указатель с немного другим синтаксисом. Когда GetObj определяется как

A& GetObj() { return *this: }

он возвращает ссылку (то есть указатель) на a. Тогда задание

a.GetObj() = 5

эффективно вызывает оператор присваивания a с аргументом 5, который изменяет значение a на 5.

Но если вы определите GetObj() как

A GetObj { return *this; }

он возвращает совершенно новый временный объект, который имеет то же значение, что и a. Поэтому, когда вы позже присвоите ему 5, это не изменит значение a.

person Adi Levin    schedule 07.01.2016
comment
Нет оператора присваивания A, принимающего int. - person StoryTeller - Unslander Monica; 07.01.2016