When you return a reference to an object from C ++, is it necessary to use the & ldquo; & amp; & rdquo; operator in the return variable?

advertisements

Say I have the following code:

#include <iostream>

using namespace std;

class Account
{
private:
    float balance;

public:
    Account() { balance = 0.0; };
    float GetBalance() { return balance; };
    void SetBalance(float newBalance) { balance = newBalance; };
};

Account mainAccount;

Account& GetAccount()
{
    return mainAccount;
}

void PrintAccountInfo()
{
    cout << "mainAccount's balance is " << mainAccount.GetBalance() << endl;
}

int main()
{
    PrintAccountInfo();
    Account &a = GetAccount(); // Line 31
    a.SetBalance(30.0);
    PrintAccountInfo();
    return 0;
}

When I run it, I get the following output (as expected):

mainAccount's balance is 0
mainAccount's balance is 30

However, on line 31, if I take out the "&" in the "Account &a", to make it this:

Account a = GetAccount(); // note lack of "&"

I get this output:

mainAccount's balance is 0
mainAccount's balance is 0

How come? I thought when returning a reference, the "&" is redundant / not necessary? Am I fundamentally misunderstanding how references work in C++?

EDIT: Thanks, I understand now why the two are different. However, then shouldn't I be able to do this:

Account GetAccount()
{
    return mainAccount;
}

int main()
{
    Account &a = GetAccount();
    // ....
}

However, when I run that, I get an error:

untitled: In function ‘int main()’:

untitled:31: error: invalid initialization of non-const reference of type ‘Account&’ from a temporary of type ‘Account’


I thought when returning a reference, the "&" is redundant / not necessary?

You thought wrong.

Consider these two different lines:

Account &a = GetAccount(); // Line 31

Account a = GetAccount(); // Line 31

In the first, you declare a reference called a which is bound to the object returned by the function GetAccount.

In the second, you declare an object a which is copy-initialized by the object returned by the function GetAccount.

Fundamentally: one declares a reference, the other declares an object.


EDIT: Answering the follow-on question:

"can I remove the & from the return type in the declaration of the GetAccount function: Account GetAccount() { return mainAccount; }"

You certainly can remove the &, but then your behavior will change. Consider these two functions:

Account GetAccount() { return mainAccount; }

Account &GetAccount() { return mainAccount; }

In the first, you return a temporary object which has been copy-initialized from the mainAccount object. In the second you return a reference to the mainAccount object.

  • If you want a to be a reference to mainAccount, you need & in both places.

  • If you want a to be a copy of mainAccount, you need no & in the declaration of a. The other declaration won't matter in this case.

  • If you want a to be a reference to a compiler-generated temporary value (hint: you don't), declare a with &, but GetAccount without.