В чем разница между передачей по ссылке в Java и передачей указателя в C?
Я изучаю Java в течение нескольких месяцев, и теперь я начинаю изучать C.
Я немного смущен, у меня сложилось впечатление, что передача объекта по ссылке и передача указателя на этот объект была одной и той же: я думал, что разница в том, что в Java все прохождение объектов выполняется с помощью указателей автоматически, где, как и в C, нужно на самом деле посыпать маленькие звездочки и амперсанды здесь и там. Недавно, в разговоре, я был уверен, что есть разница!
В чем разница между передачей по ссылке и передачей указателя?
Ответы
Ответ 1
Ни Java, ни C не имеют pass-by-reference. Они оба строго проходят по значению.
Семантика Pass-by-reference означает, что при изменении значения параметра в методе вызывающая сторона увидит это изменение в аргументе.
Теперь вы можете подумать: "Но это случай в Java! Если я изменяю объект во время метода, вызывающий видит это изменение". Объект не является параметром. Параметр - это просто переменная - и если вы измените значение этой переменной, вызывающий объект не увидит этого. Например:
public void foo(Object x)
{
x = null;
}
public void caller()
{
Object y = new Object();
foo(y);
// y is still not null!
}
Если параметр был действительно передан по ссылке, y
после этого будет пустым. Вместо этого значение y
является просто ссылкой, и эта ссылка передается по значению. Это сбивает с толку, потому что слово "ссылка" находится в обоих терминах, но они разные.
Вы можете посмотреть мою статью о передаче параметра С#, чтобы узнать, что было бы возможно, если бы у Java действительно была передача по ссылке семантика, поскольку С# делает, когда (и только когда) вы используете ключевое слово ref
.
Вы также можете посмотреть комментарии моего ответа на переполнение стека, связанные с темой.
Ответ 2
Я думал, что разница в том, что в Java все прохождение объектов выполняется с помощью указателей автоматически, где, как и в C, нужно на самом деле посыпать маленькие звездочки и амперсанды здесь и там.
Концептуально, это совершенно правильно. Если мы педантичны (и это хорошо), мы можем даже сказать, что объекты вообще не передаются на Java. То, что передается, является только "указателем", который в Java называется ссылкой. Все косвенные действия выполняются автоматически. Поэтому, когда вы выполняете "objref- > foo" вместо "objref.foo" в C и не можете использовать точку, потому что работаете с указателем, в Java вы все равно можете использовать точку, потому что она ничего не знает о все равно. В C вы можете передать указатель (и здесь он на самом деле называется указателем), и вы можете передать сам объект, и в этом случае будет передана копия. В C вы получаете доступ к объекту, на который указатель ссылается по косвенности с помощью звезды или "- > ". В Java единственный способ доступа к объектам - использовать точку (objref.member).
Если мы снова педантичны (теперь более важно снова), ни на Java, ни на C нет "пройти по ссылке". То, что мы передаем в Java, является ссылкой/указателем на объект, а в C мы либо передаем копию объекта (очевидный случай), либо снова передаем копию указателя на объект. Таким образом, в обоих случаях - Java и C - то, что мы передаем, - это адреса объектов. Не говоря о примитивных типах Java, которые копируются как на Java, так и на C, даже если вы можете передавать их адрес в C, нет никакой разницы между агрегированным типом (т.е. Структурой) и "примитивным типом" на C в этом что касается.
Ответ 3
Различия тонкие. На уровне сборки в обоих случаях адрес объекта передается функции. Однако в случае с указателем параметр является независимым указателем, который может использоваться для изменения целевого объекта (* pch = 'x') или может использоваться для доступа к другому объекту (pch = "newstr" ). В исходном случае параметр автоматически коснется целевого объекта.
Ответ 4
Несколько вещей
- C не имеет ссылок (несмотря на С++)
- Java не имеет указателей.
- Разница между указателями и ссылками заключается в том, что указатели - это адреса памяти, с которыми вы можете рассчитывать. Ссылки не могут быть рассчитаны с помощью
- Java и C pass by value (При передаче объекта в Java ссылка копируется в функцию)
Ответ 5
Я считаю, что указатель - это переменная, содержащая ссылку.
С помощью вы можете получить направление памяти (ссылку), а с помощью * вы можете получить доступ к содержимому направления памяти.
Я предлагаю книгу Язык программирования C..
Привет
Ответ 6
True pass-by-reference означает, что вы можете назначить новое значение ссылке, и это новое значение будет отображаться в вызывающий контекст, как и внутри вызываемого метода.
В Java это невозможно, потому что ссылки на объекты передаются по значению.
Ответ 7
Если вы изучаете C (а не С++), то ссылок нет.
Термин "передать по ссылке" на C просто означает, что вы передаете указатель как адрес, в котором будет сохранено значение, чтобы функция могла изменить свое значение.
В противном случае вы передаете значение, что означает, что копия переменной генерируется в стеке, а изменения не влияют.
Во многом это похоже на то, что вы видите на Java, за исключением того, что в Java вам не нужно явно превращать вещи в указатель или разыменовывать их. Другими словами, когда вы передаете указатель, адрес копируется в стек, поэтому, если ваша функция меняет указатель (а не данные, на которые он указывает), изменения исчезают, когда вы закончите с функцией. Точно так же, когда вы передаете ссылку на объект в Java, вы можете изменить содержимое объекта (например, вызовом функций), но изменение значения varialbe на объект anothr не будет иметь эффекта, как только вы уйдете.
Если вы использовали С++ (который похож на C), вы можете пройти по ссылке, и в этом случае вам не нужно иметь дело с указателями, а изменения в переменной в функции фактически меняют внешнее значение напрямую ( за исключением того, что вы не можете указать на что-то еще).
Ответ 8
Вот недавняя статья Эрика Липперта об этом. Он программист на компиляторе С#, но все, что он говорит, имеет достаточную общность, чтобы быть распространенным на другие языки GC, такие как Java:
http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx
Цитата из статьи:
Указатели строго "более мощны", чем ссылки; все, что вы можете сделать со ссылками, которые вы можете сделать с указателями. [...]
Указатели обычно реализуются как адреса. Адрес - это число, которое является смещением в "массив байтов", который является всем виртуальным адресным пространством процесса. [...]
По всем этим причинам мы не описываем ссылки как адреса в спецификации. Спецификация просто говорит, что переменная ссылочного типа "хранит ссылку" на объект и оставляет ее полностью неопределенной в отношении того, как это может быть реализовано. Точно так же указательная переменная хранит "адрес" объекта, который опять остается довольно расплывчатым. Нигде мы не говорим, что ссылки совпадают с адресами.
Итак, в С# ссылка - это какая-то неопределенная вещь, которая позволяет ссылаться на объект. Вы ничего не можете сделать со ссылкой, кроме разыменования, и сравнить ее с другой ссылкой для равенства. А в С# указатель идентифицируется как адрес.
В отличие от ссылки, вы можете сделать гораздо больше с указателем, содержащим адрес. Адресами можно манипулировать математически; вы можете вычесть одно из другого, вы можете добавить к ним целые числа и т.д. Их юридические действия указывают на то, что они представляют собой "причудливые числа", которые индексируются в "массив", который является виртуальным адресным пространством процесса.
Ответ 9
Те читатели, которые знакомы с C/С++, вероятно, заметили, что ссылки на объекты появляются
быть похожим на указатели. Это подозрение, по сути, правильно. Ссылка на объект
аналогично указателю на память. Основное различие - и ключ к безопасности Javas - это то, что
вы не можете манипулировать ссылками, поскольку вы можете использовать фактические указатели. Таким образом, вы не можете вызвать
объект ссылается на произвольное место памяти или манипулирует им как целое число.
- java не поддерживается и оператором, то как можно получить адрес объекта в java.
- В java-ссылке делается объект, например
MyClass object1 = new MyClass();
MyClass object2 = object1;
то есть. вы можете подумать, что object1 и object2 относятся к отдельным и отдельным объектам.
Однако это было бы неправильно. Вместо этого, после выполнения этого фрагмента, object1 и object2 будут ссылаться на один и тот же объект. если вы измените какой-либо другой эффект.
* вы не можете изменить адрес объекта после инициализации
i.e MyClass obj = new MyClass();
как ссылка в С++, с объектом вы можете изменить только значение экземпляра объекта
Примечание. java предоставляет специальную функцию object1 имеет значение null, но object2 все еще указывает на исходный объект.
Ответ 10
Я не уверен в Java, но на С# или VB.net вы можете пройти по значению или по refrence
пример передачи по refrence
static void Main(string[] args)
{
int x = 1;
Foo(ref x);
Console.WriteLine(x.ToString());//this will print 2
}
private static void Foo(ref int x)
{
x++;
}
обратите внимание, что x равно 1, но когда вы вызываете метод Foo и передаете x по refrence, когда x увеличивается на единицу в Foo, исходное значение также увеличивается