私も同様のコードに困惑しました-最初は。それは「なぜ私が関数呼び出しに値を代入するのか、なぜコンパイラーはそれに満足するのか?」ということでした。私は自問自答しました。しかし、「背後」で何が起こっているかを見ると、それは理にかなっています。
cppや他の人が指摘したように、左辺値はアドレスを持つ「メモリ ロケーション」であり、値を割り当てることができます。lvalues と rvalues のトピックについては、インターネットで詳細を見つけることができます。
関数を見ると:
int& fun()
{
static int x = 10;
return x;
}
& を型に移動したので、int への参照を返していることがより明確になります。左辺値であるx
がある
ことがわかります。これにはアドレスがあり、それに割り当てることができます。また、静的であるため、特別です。静的でない場合、変数の有効期間 (スコープ) は、関数を終了するときにスタックの巻き戻しで終了し、参照は、宇宙に存在するブラック ホールを指す可能性があります。ただし、xは静的であるため、関数を離れた後も (そして再び関数に戻ったときも) 存在し、関数の外部からアクセスできます。
int への参照を返しています。 x を返すため、 xへの参照です。次に、参照を使用して、関数の外側でxを変更できます。そう:
int main()
{
fun();
関数を呼び出すだけです。変数x (fun 関数のスコープ内) が作成され、値 10 が割り当てられます。関数が終了した後でもアドレスと値は存在しますが、アドレスがないため、その値を使用できません。
fun() = 30;
関数を呼び出して、xの値を変更します。x値は、関数によって返される参照を介して変更されます。注:関数は最初に呼び出され、関数呼び出しが完了した後にのみ呼び出され、次に割り当てが行われます。
int& reference_to_x = fun(); // note the &
ここで、関数によって返されたxへの参照を (最終的に) 保持します。これで、最初に関数を呼び出さずにxを変更できます。( reference_to_xはおそらくxが fun 関数内に持っているのと同じアドレスを持つでしょう)
int copy_of_x = fun(); // no & this time
今回は新しい int を作成し、(参照を介して) xの値をコピーするだけです。この新しい int には独自のアドレスがあり、reference_to_xのようにxを指していません。
reference_to_x = 5;
参照を介してxに値 5を割り当てましたが、関数は呼び出しませんでした。copy_of_xは変更されません。
copy_of_x = 15;
新しい int を値 15 に変更しました。copy_of_xには独自のアドレスがあるため、 xは変更されません。
}
6502と他の人が指摘したように、コンテナーとカスタム オーバーライドで多くの参照を返すことで同様のアプローチを使用します。
std::map<std::string, std::string> map = {};
map["hello"] = "Ahoj";
// is equal to
map.operator[]("hello") = "Ahoj"; // returns reference to std::string
// could be done also this way
std::string& reference_to_string_in_map = map.operator[]("hello");
reference_to_string_in_map = "Ahoj";
使用する map 関数は、次のような宣言を持つことができます。
std::string& map::operator[]( const std::string& key ); // returns reference
マップに「格納」した文字列へのアドレスがないため、マップのこのオーバーライドされた関数を呼び出し、キーを渡して、マップがアクセスしたい文字列を認識し、その文字列への参照を返します。を使用して値を変更できます。注: ここでも、関数が最初に呼び出され、関数が完了した後にのみ (map が正しい文字列を見つけ、それへの参照を返した)、代入が行われます。それは fun() = 10 のようなもので、より美しいだけです...
これが、他の回答を読んでもまだすべてを理解していない人の助けになることを願っています...