Reputation: 1571
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’
Upvotes: 4
Views: 155
Reputation: 179779
To answer the question from the title: Not directly.
typedef Account& AccountRef; // Hiding here
AccountRef GetAccount()
{
return mainAccount;
}
BTW, &
isn't used as an operator here. It modifies the Account
type. It can be used as an unary and binary operator, e.g. in &obj
or 5 & 6
. When used as an operator, it must appear before or between expressions.
Upvotes: 0
Reputation: 168596
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 theGetAccount
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.
Upvotes: 3
Reputation: 258548
You return a reference, but you then create a new object using that reference. a
is the new object that gets copy-initialized using the reference returned from GetAccount
.
Remember, a reference is an alias. It's like saying:
int x = 0;
int& y = x;
int z = y;
//is equivalent to
z = x;
z
doesn't refer to x
nor y
in this case, because z
itself isn't a reference.
So:
x = 1;
would modify both x
and y
, but z
would still be 0.
Upvotes: 2
Reputation: 20191
In both cases you return a reference, but there is a difference in how you use it:
Account &a = GetAccount();
In this case you use the reference to initialize another reference, making a
a reference to the original Data.
Account a = GetAccount();
In this case you use your returned reference to initialize an object of type Account
, instead of a reference to Account. Therefore you copy the original object into the newly created a
.
Upvotes: 2
Reputation: 92211
It does matter.
This version
Account a = GetAccount(); // note lack of "&"
creates a copy of the account, not a reference. Therefore when changing the balance, you change the balance of the copy, not the original.
Upvotes: 0