Я знаю всю концепцию передачи по ссылке в C & C ++ и аналогичная концепция передачи по значению только в Java.
Но с точки зрения Все проходит по значению, не так ли?
В C мы передаем указатель переменной в функцию. Таким образом, мы просто передаем значение ссылки на функцию. Именно поэтому мы говорим, что Java не поддерживает передачу по ссылке, потому что мы просто передаем значение ссылочной переменной в функции. Таким образом, мы передаем ссылку по значению. Хотя в C ++ есть способ передачи по ссылке, так как мы можем передавать аргументы, и функция будет работать с той же ячейкой памяти, используя этот формат
void swap(int &x, int &y)
Но передача по ссылке с помощью указателей в C — это просто передача указателей по значению.
void swap(int* x, int* y)
Я знаю, что вопрос может показаться немного глупым, но я чувствую, что во всей моей концепции есть большая зияющая дыра. Так каково фактическое определение вызова по ссылке, это просто псевдо-имя вызова по значению в другом контексте?
Два основных момента:
Передать по значению: вызываемая функция создает новый набор переменных в стеке и копирует в них значения аргументов.
Передать по ссылке: вместо передачи значений вызываемой функции передаются ссылки / указатели на исходные переменные.
Почему программисты говорят, что «передача по ссылке» на самом деле «передача ссылок по значению?»
При передаче ссылок / указателей на исходные переменные фактически объекты / адреса передаются по значению. Таким образом, вы можете сказать, что передача по ссылке передача ссылки по значению но это не значит, что передать по ссылке это псевдо имя передать по значению. Разница между ними хорошо объяснена в этот ответ. Я копирую отрывок:
Если я скажу вам URL, я проходя по ссылке. Вы можете использовать этот URL, чтобы увидеть та же веб-страница Я могу видеть. Если эта страница изменилась, мы оба увидим изменения. Если вы удаляете URL, все, что вы делаете, это уничтожаете вашу ссылку на эту страницу — вы не удаляете саму страницу.
Если я распечатаю страницу и дам вам распечатку, я проходя по значению. Ваша страница является отключенной копией оригинала. Никаких последующих изменений вы не увидите, а внесенные вами изменения (например, пометки на распечатке) не будут отображаться на исходной странице. Если вы уничтожите распечатку, вы фактически уничтожили ваша копия объекта — но оригинальная веб-страница остается нетронутой.
Передача по ссылке означает, что параметр вызываемых функций будет таким же, как переданный аргумент вызывающего (не значение, а идентификатор — сама переменная). Передача по значению означает, что параметр вызываемых функций будет копией переданного аргумента вызывающей стороны. Значение будет одинаковым, но идентичность — переменная — отличается. Таким образом, изменение параметра, выполняемого вызываемой функцией, в одном случае изменяет передаваемый аргумент, а в другом случае просто изменяет значение параметра в вызываемой функции (которая является только копией).
Простой пример в C ++
#include <iostream>
void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }
int main()
{
int x = 0;
by_val(x); std::cout << x << std::endl; // prints 0
by_ref(x); std::cout << x << std::endl; // prints 2
int y = 0;
by_ref(y); std::cout << y << std::endl; // prints 2
by_val(y); std::cout << y << std::endl; // prints 2
}
C ++ определяется стандартными ошибками по модулю. Стандарт C ++ не определяет, как реализованы ссылки и как они передаются в функции. Он также не определяет соглашения о вызовах в целом и не определяет макет указателя, стек, кучу или множество других деталей реализации.
Вместо этого он пытается определить, что означает код C ++.
Ссылки в конечном итоге являются псевдонимами других ценностей. Наиболее распространенный способ их реализации — это указатель изнутри: но поскольку нет доступа к этому значению указателя или побочным эффектам от доступа через него, это позволяет компиляторам полностью исключить существование ссылки и просто используйте указанное значение непосредственно.
Если компилятор не может этого сделать, он обычно передает указатель или эквивалент.
Несмотря на то, что его часто используют в качестве указателя, он все же отличается, так как семантика взаимодействия с ним различна: они не могут быть повторно найдены, у них не может быть получен их адрес, и они не могут быть неинициализированы (нулевыми или эквивалентными).
Естественно, эти правила могут быть нарушены с помощью неопределенного поведения.
Вы не можете сказать, что «передача по ссылке» — это действительно «передача по значению» без определения «ссылка».
В Джава, утверждение истинно (вначале прибл.), потому что внутри функции вы можете изменить значение формального параметра, который является ссылкой, без изменения значения параметра, переданного в вызове:
void f(Object param) {
param = null;
}
void g() {
Object o = new Object();
System.out.println(o);
f(o);
System.out.printn(o);
}
Всем известно, что два печатных оператора дадут одинаковые результаты. по факту на Яве нет передачи по ссылке, есть только ссылки, которые можно передать; и есть только один способ передать аргументы: по значению.
В C ++, это действительно другое. Когда вы изменяете значение ссылочного параметра внутри функции, параметр, передаваемый в вызове, изменяется:
void f(int ¶m) {
param = 0;
}
void g() {
int i=12;
cout << i << endl;
f(i);
cout << i << endl;
}
Каждый программист C ++ знает, что на втором отпечатке будет отображаться 0 (а на первом — 12).
Поэтому в C ++ нельзя сказать, что «передача по ссылке» — это «передача ссылки по значению». В C ++ ссылки не имеют значения, это просто имена, связанные с кусками памяти (Стандартный раздел 8.3.2 Ссылка: [Примечание: Ссылку можно рассматривать как имя объекта. — конец примечания]). внутри f()
есть только одна переменная, которая имеет два имени. Конечно, вы можете возразить, что большинство реализаций ссылок C ++ являются скрытыми указателями, поэтому утверждение может быть истинным; но вы должны знать, что во многих случаях можно избежать использования скрытых указателей для реализации ссылок (Стандартный раздел 8.3.2 / 7 Список литературы. Не указано, требуется ли ссылка для хранения) … Так что в C ++ утверждение недействительно. В C ++ действительно есть два способа передачи параметров: по значению и по ссылке.