Уже есть отличные ответы, которые охватывают это. Я хотел бы внести небольшой вклад, поделившись очень простым примером (который будет скомпилирован), сравнивающим поведение между передачей по ссылке в c ++ и передачей по значению в Java.
Несколько баллов:
- Термин ссылка перегружен. В Java это просто означает указатель. В термине «Передача по ссылке» это означает ссылку на исходную переменную, которая была передана.
- Java является передачей по значению , но позволяет нам эмулировать передачу по ссылке, передавая ссылку на Java (то есть указатель) по значению. Это означает, что он передает копию ссылки Java.
- C ++ допускает передачу по ссылке , объявляя опорный параметр с помощью символа «&» (который является тем же символом, который используется для обозначения «адреса переменной» как в C, так и в C ++ ). Например, если мы передадим указатель, параметр и аргумент не просто указывают на один и тот же объект, но на то, что они являются одной и той же переменной. Если один из них настроен на другой адрес или имеет значение NULL, то же самое можно сказать и о другом.
- В приведенном ниже примере C ++ я передаю указатель на завершенную нулем строку по ссылке . И в приведенном ниже примере с Java я передаю ссылку на Java на строку (опять же, так же, как указатель на строку) по значению. Обратите внимание на вывод в комментариях.
C ++ передача по ссылочному примеру:
using namespace std;
#include <iostream>
void change (char *&str){ // the '&' makes this a reference parameter
str = NULL;
}
int main()
{
char *str = "not Null";
change(str);
cout<<"str is " << str; // ==>str is <null>
}
Java передает "ссылку на Java" по значению примера
public class ValueDemo{
public void change (String str){
str = null;
}
public static void main(String []args){
ValueDemo vd = new ValueDemo();
String str = "not null";
vd.change(str);
System.out.println("str is " + str); // ==> str is not null
}
}
EDIT
Несколько человек написали комментарий, который, кажется, указывает, что либо они не смотрят на мои примеры, либо не получают пример c ++. Не уверен, где разъединение, но угадать пример c ++ не ясно. Я публикую пример на Паскале, потому что я думаю, что переход по ссылке выглядит на Паскале чище, но я могу ошибаться. Я мог бы просто запутывать людей больше; Я надеюсь, что нет.
В паскале параметры, передаваемые по ссылке, называются "параметрами вар". В процедуре setToNil ниже обратите внимание на ключевое слово «var», которое предшествует параметру «ptr». Когда указатель передается этой процедуре, он будет передан по ссылке . Обратите внимание на поведение: когда эта процедура устанавливает для ptr значение nil (это говорит на паскале для NULL), она устанавливает для аргумента значение nil - вы не можете сделать это в Java. (Мой Паскаль не так хорош, как давно.)
program passByRefDemo;
type
iptr = ^integer;
var
ptr: iptr;
procedure setToNil(var ptr : iptr);
begin
ptr := nil;
end;
begin
new(ptr);
ptr^ := 10;
setToNil(ptr);
if (ptr = nil) then
writeln('ptr seems to be nil'); { ptr should be nil, so this line will run. }
end.
РЕДАКТИРОВАТЬ 2
Некоторые выдержки из "Язык программирования Java" Кена Арнольда, Джеймса Гослинга (парня, который изобрел Java) и Дэвида Холмса, глава 2, раздел 2.6.5
Все параметры методов передаются "по значению" . Другими словами,
значения переменных параметра в методе являются копиями инвокера
указано в качестве аргументов.
Он продолжает делать то же самое в отношении объектов. , ,
Следует отметить, что когда параметр является ссылкой на объект, он
ссылка на объект, а не сам объект, то есть передается "по значению" .
И в конце того же раздела он делает более широкое утверждение о том, что java передается только по значению и никогда не передается по ссылке.
Язык программирования Java не передает объекты по ссылке; он
передает ссылки на объекты по значению . Потому что две копии одного и того же
ссылка ссылается на тот же фактический объект, изменения, сделанные через один
ссылочная переменная видна через другую. Есть ровно один
режим передачи параметров - передача по значению - и это помогает сохранить вещи
простой.
В этом разделе книги дается отличное объяснение передачи параметров в Java и различия между передачей по ссылке и передачей по значению, созданной Java. Я бы посоветовал любому прочитать его, особенно если вы все еще не убеждены.
Я думаю, что разница между этими двумя моделями очень тонкая, и если вы не программировали там, где фактически использовали переход по ссылке, легко пропустить, где две модели различаются.
Я надеюсь, что это решит спор, но, вероятно, не будет.
РЕДАКТИРОВАТЬ 3
Возможно, я немного одержим этим постом. Возможно, потому что я чувствую, что создатель Java непреднамеренно распространяет дезинформацию. Если вместо использования слова «ссылка» для указателей они использовали что-то еще, скажем,
черт возьми, не было бы никаких проблем. Вы можете сказать: «Java передает dingleberry по значению, а не по ссылке», и никто не будет смущен. (Следовательно, при обращении к ссылке «проход по ссылке против значения» я буду ссылаться на ссылки как на пустые слова.)
Это причина, по которой только разработчики Java имеют проблемы с этим. Они смотрят на слово «ссылка» и думают, что точно знают, что это значит, поэтому они даже не удосуживаются рассмотреть противоположный аргумент.
В любом случае, я заметил комментарий кого-то блестящего, который сделал аналогию с воздушным шаром, которая мне действительно понравилась. Настолько, что я решил склеить несколько картинок, чтобы сделать набор мультфильмов, чтобы проиллюстрировать это. Больше не могу найти комментарии, иначе я бы отдал человеку должное. (Есть шанс, что я неправильно помню, и именно я составил аналогию. В этом случае я мог бы быть блестящим; я даже могу быть «гением стабильности».)
Передача ссылки по значению - Изменения в ссылке не отражаются в области видимости вызывающего, но изменения в объекте есть. Это потому, что ссылка копируется, но и оригинал, и копия ссылаются на один и тот же объект.
Передать по ссылке - Копия ссылки отсутствует. Одиночная ссылка является общей как для вызывающей стороны, так и для вызываемой функции. Любые изменения в ссылке или данных объекта отражаются в области действия вызывающей стороны.