Я тоже был отгорожен аналогичным кодом - в кулаке. «Почему, черт возьми, я назначаю значение вызову функции, и почему компилятор ему доволен?» Я расспросил себя. Но когда вы смотрите на то, что происходит «позади», это имеет смысл.
Как cpp и другая poined вне, lvalues являются «ячейками памяти», которые имеют адрес, и мы можем присвоить им значение. Вы можете найти больше на тему lvalues и rvalues on the internet.
Когда мы посмотрим на функцию:
int& fun()
{
static int x = 10;
return x;
}
Я переехал & к типу, так что это более очевидно, что мы возвращаемся ссылка на междунар.
Мы видим, что у нас есть x, который является lvalue - он имеет адрес, и мы можем назначить ему. Он также является статичным, что делает его особенным - если он не был статичным, время жизни (область действия) переменной заканчивалось отказом стека после выхода из функции, а затем ссылка могла указывать на то, какая черная дыра существует во вселенной. Однако, поскольку x является статическим, он будет существовать даже после того, как мы оставим функцию (и когда мы снова вернемся к функции), и мы можем получить к ней доступ за пределами функции.
Мы возвращаемся ссылку на междунар, и так как мы вернуть х, это ссылка на х. Затем мы можем использовать ссылку для изменения функции x вне функции. Таким образом:
int main()
{
fun();
Мы просто вызываем функцию. Переменная x (в рамках функции fun) создана, она имеет значение 10 назначенных. Его адрес и значение существуют даже после того, как функция оставлена, но мы не можем использовать ее, поскольку у нас ее нет.
fun() = 30;
Мы называем функцию, а затем изменить значение х. Значение x изменяется через ссылку, возвращаемую функцией. ПРИМЕЧАНИЕ: эта функция называется первой и только после того, как вызов функции был завершен, тогда происходит назначение.
int& reference_to_x = fun(); // note the &
Теперь мы (наконец) сохранить ссылку на х возвращенной функции. Теперь мы можем изменить x без вызова функции в первую очередь.(reference_to_x будет, вероятно, имеет один и тот же адрес, как х есть внутри функции забавной)
int copy_of_x = fun(); // no & this time
На этот раз мы создаем новый ИНТ, и мы просто скопировать значение х (через ссылку). Этот новый int имеет свой собственный адрес, он не указывает на x, как reference_to_x есть.
reference_to_x = 5;
Мы присвоили х значение 5 через ссылку, и мы даже не будем называть функцией. Код copy_of_x не изменяется.
copy_of_x = 15;
Мы изменили новый Int дорожить 15. х не изменяется, так как copy_of_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";
Функция карта, которую мы могли бы использовать заявление, как это:
std::string& map::operator[](const std::string& key); // returns reference
Мы не имеем адрес в строку мы «хранится» в карте, поэтому мы называем эту перекрытый функцию отображения , передавая его, так что карта знает, к какой строке мы хотели бы получить доступ, и возвращает нам ссылку на эту строку, которую мы можем использовать для изменения значения. ПРИМЕЧАНИЕ: снова функция вызывается в первую очередь и только после ее завершения (карта найдена правильная строка и возвращает ссылку на нее) назначение происходит. Это как с удовольствием() = 10, только более красивыми ...
Надеется, что это помогает всем, кто до сих пор woudn't все понять даже после прочтения других ответов ...
Возвращаясь ссылки на статические переменный-значении (и юридическое). Почему вы думаете, что должны быть какие-то ошибки? –
Возвращаемое значение из 'fun()' is 'int &' которое является 'lvalue' –
Оценка ссылки * приводит к * значению l. –