4

次のコードがあるとします。

#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;
}

実行すると、次の出力が得られます (予想どおり)。

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

しかし、31行目の「Account &a」の「&」を外すと、こうなります。

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

私はこの出力を得ます:

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

どうして?参照を返すとき、「&」は冗長/不要だと思いましたか? C++ で参照がどのように機能するかを根本的に誤解していますか?

編集: ありがとうございます。なぜこの 2 つが違うのか理解できました。しかし、私はこれを行うことができないはずです:

Account GetAccount()
{
    return mainAccount;
}

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

ただし、それを実行すると、エラーが発生します。

無題: 関数 'int main()' 内:

untitled:31: エラー: タイプ 'Account' のテンポラリからのタイプ 'Account&' の非 const 参照の無効な初期化</p>

4

5 に答える 5

3

参照を返すとき、「&」は冗長/不要だと思いましたか?

あなたは間違って考えました。

次の 2 つの異なる行を検討してください。

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

Account a = GetAccount(); // Line 31

a最初に、関数によって返されるオブジェクトにバインドされる参照を宣言しますGetAccount

a2 番目では、関数によって返されるオブジェクトによってコピー初期化されるオブジェクトを宣言しますGetAccount

基本的に: 1 つは参照を宣言し、もう 1 つはオブジェクトを宣言します。


編集: 後続の質問に答える:

"関数の宣言で戻り値の型からを削除できますか:&GetAccountAccount GetAccount() { return mainAccount; } "

確かに を削除でき&ますが、そうすると動作が変わります。次の 2 つの関数を検討してください。

Account GetAccount() { return mainAccount; }

Account &GetAccount() { return mainAccount; }

最初に、オブジェクトからコピー初期化された一時オブジェクトを返しmainAccountます。次に、オブジェクトへの参照を返しmainAccountます。

  • aへの参照になりたい場合は、両方の場所mainAccountに必要です。&

  • aのコピーになりたい場合は、 の宣言にmainAccountno は必要ありません。この場合、他の宣言は問題になりません。&a

  • コンパイラによって生成された一時的な値への参照になりたい場合a(ヒント: 必要ありません)、awith&で宣言しますが、GetAccountなしで宣言します。

于 2012-09-06T20:25:57.253 に答える
2

参照を返しますが、その参照を使用して新しいオブジェクトを作成します。aから返された参照を使用してコピー初期化される新しいオブジェクトですGetAccount

参照はエイリアスであることを忘れないでください。それは次のように言っているようなものです:

int x = 0;
int& y = x;

int z = y;
//is equivalent to
z = x;

zそれ自体は参照ではないため、この場合も参照しませんxyz

そう:

x = 1;

と の両方を変更しxますyが、zそれでも 0 です。

于 2012-09-06T20:23:01.860 に答える
2

どちらの場合も参照を返しますが、使用方法に違いがあります。

Account &a = GetAccount(); 

この場合、参照を使用して別の参照を初期化aし、元のデータへの参照を作成します。

Account a = GetAccount(); 

この場合、AccountAccount への参照ではなく、返された参照を使用して type のオブジェクトを初期化します。したがって、元のオブジェクトを新しく作成した にコピーaします。

于 2012-09-06T20:26:18.427 に答える
0

タイトルからの質問に答えるには:直接ではありません。

typedef Account& AccountRef; // Hiding here
AccountRef GetAccount()
{
    return mainAccount;
}

ところで、&ここでは演算子として使用されていません。タイプを変更しAccountます。&objor などの単項および二項演算子として使用できます5 & 6。演算子として使用する場合は、式の前または間に表示する必要があります。

于 2012-09-07T08:35:55.823 に答える
0

それは問題である。

このバージョン

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

参照ではなく、アカウントのコピーを作成します。したがって、バランスを変更するときは、オリジナルではなくコピーのバランスを変更します。

于 2012-09-06T20:25:17.317 に答える