我一直在学习Java的几个月,我现在开始学习C.在Java中传递引用和在C中传递指针有什么区别?
我有点困惑,我的印象是,通过引用传递对象和指针传递到该对象是相同的事情:我认为不同的是,在Java中,所有对象的传递都是自动完成指针的,在C中,实际上在这里和那里实际上要洒上星号和&符号。最近,在谈话中,我确信有一个区别!
通过引用传递和传递指针有什么区别?
我一直在学习Java的几个月,我现在开始学习C.在Java中传递引用和在C中传递指针有什么区别?
我有点困惑,我的印象是,通过引用传递对象和指针传递到该对象是相同的事情:我认为不同的是,在Java中,所有对象的传递都是自动完成指针的,在C中,实际上在这里和那里实际上要洒上星号和&符号。最近,在谈话中,我确信有一个区别!
通过引用传递和传递指针有什么区别?
Java既不是Java 也不是 C具有传递引用。他们都严格按价值传递。
传递引用语义意味着当您更改方法中参数的值时,调用方将在参数中看到该更改。
现在,您可能会想:“但是在Java中就是这种情况!如果在方法中更改对象,调用者会看到这种变化。” 该对象不是参数。参数是只是该变量 - 如果您更改该变量的值,调用者将看不到。例如:
public void foo(Object x)
{
x = null;
}
public void caller()
{
Object y = new Object();
foo(y);
// y is still not null!
}
如果该参数是真的按引用传递,y
将是空之后。相反,y
的值只是一个参考,并且该参考值是按值传递的。这是令人困惑的,因为“参考”这个词有两种含义,但它们是不同的东西。
你可能想看看my article about C# parameter passing,看看什么是可能的,如果Java的确实有传递引用语义,如C#做时(且仅当)您使用ref
关键字。
您可能还想看看与该主题相关的评论my Stack Overflow answer。
差异很微妙。在汇编级别,在这两种情况下,对象的地址都被传递给函数。但是,在指针情况下,参数是一个独立的指针,可用于修改目标对象(* pch ='x')或可用于访问不同的对象(pch =“newstr”)。在参考案例中,该参数会自动指向目标对象。
如果你正在学习C(而不是C++),那么就没有参考。
C中的术语“通过引用传递”仅仅意味着你传递一个指针作为存储值的地址,以便该函数可以更改其值。 否则,您正在传值,这意味着在堆栈上生成变量的副本,并且修改没有影响。
在许多方面,这与您在Java中看到的类似,只不过在Java中您不必将事物明确地转换为指针或对其进行解引用。换句话说,当你传递一个指针时,地址被复制到堆栈中,所以如果你的函数改变指针(而不是指向它的数据),当你完成这个函数时,这些改变就会消失。同样,当您在Java中传递对象引用时,可以更改对象的内容(例如,通过调用函数),但是如果将变量指向anothr对象,则离开后无效。
如果您使用C++(看起来像C),那么您可以通过引用传递,在这种情况下,您不需要处理指针,并且对函数中变量的更改实际上直接更改外部值(除了你不能指向别的东西)。
有几件事情
我建议你从最后一个项目符号中删除“默认”一词 - C和Java按值传递,故事结束。 – 2009-03-01 22:32:30
相信一个指针是一个包含一个参考的变量。 随着&你可以获得一个内存方向(参考),并与*你可以访问内存方向的内容。 我建议书The C programming Language。
问候
真pass-by-reference意味着你可以在新的值赋给参考,而这个新的价值将是一样的内部调用方法调用的上下文可见。
在Java中,这是不可能的,因为object references are passed by value。
Eric Lippert最近有一篇关于这方面的文章。他对C#编译器的程序员,但无论他说,有有足够的普遍性扩展到其他GC语言如Java:从文章
http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx
报价:
指针是严格比引用更“强大”;任何你可以用引用来做的事情,你可以用指针来做。 [...]
指针通常作为地址来实现。地址是一个数字,它是“字节数组”的偏移量,即进程的整个虚拟地址空间。 [...]
由于所有这些原因,我们没有在说明书中将引用描述为地址。该规范只是说,引用类型的变量“存储引用”给一个对象,并且对于如何实现这个对象而言完全模糊不清。同样,一个指针变量存储一个对象的“地址”,这个对象仍然很模糊。我们没有任何地方说参考地址与地址相同。
所以,在C#中,引用是一些模糊的东西,可以让你引用一个对象。除了解引用外,你不能对引用做任何事情,并将其与另一个引用进行比较以获得相等性。而在C#中,一个指针被识别为一个地址。
与引用相比,您可以使用包含地址的指针做更多的事情。地址可以通过数学操作;你可以从另一个中减去一个,你可以为它们添加整数,等等。他们的合法操作表明他们是“幻想号码”,它们将索引到“阵列”中,即“虚拟地址空间”。
这是在谈论引用而不是“通过参考” - 它们是相关但不同的概念。 – 2009-03-01 22:31:01
我认为不同的是,在Java中,所有对象的传递都是用指针自动完成的,因为在C中必须实际在这里和那里洒小星号和&符号。
概念,这是非常正确的。如果我们是迂腐的(这是一件好事),我们甚至可以说Java根本不会传递对象。传递的只是“指针”,在Java中被称为引用。所有间接都是自动完成的。所以,当你在C中使用“objref-> foo”而不是“objref.foo”,并且不能使用点因为你使用了一个指针,所以在Java中你仍然可以使用这个点,因为它不知道任何其他的无论如何,访问成员。在C中,你可以传递指针(在这里,它是实际上叫做指针)和你可以传递这个对象本身,在这种情况下传递一个副本。在C中,可以使用星号或“ - >”通过间接访问指针指向的对象。在Java中,无论如何访问对象的唯一方法是使用点(objref.member)。
如果我们再次迂回(现在更重要),Java和C都没有“通过引用”。我们在Java中传递的是指向对象的引用/指针,在C中,我们传递对象的副本(明显的情况),或者我们再次传递指向对象的指针副本。所以在这两种情况下 - Java和C - 我们传递的是对象的地址。不是在讨论使用Java和C复制的原始Java类型 - 即使您也可以使用C语言传递它们的地址,集合类型(即结构)和C中的“原始类型”在中没有区别那方面。
林不知道有关Java,但在C#或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增加1时,方法Foo和x通过引用传递x原始值也增加
那些熟悉C/C++的读者可能已经注意到对象引用出现 与指针类似。这种怀疑本质上是正确的。对象引用是 类似于内存指针。主要的区别 - 也是Java安全性的关键 - 您无法操作引用,因为您可以使用实际的指针。因此,不能使对象引用指向任意的内存位置或像整数一样操作它。
MyClass的object1 =新MyClass的(;
MyClass object2 = object1;
即你可能认为object1和object2引用单独和不同的对象。 但是,这将是错误的。相反,在执行此片段后,object1和object2都将引用同一个对象。如果你改变其他任何一种效果。你可以在初始化后不改变对象的地址 即MyClass obj = new MyClass(); 作为C++的参考,带对象只能改变对象实例的值
注意:java提供了一个特殊的功能 object1被设置为null,但object2仍然指向原始对象。
嘿,可以这样说:“指针”是一种数据类型,“引用”只是一种处理数据的方式?一个是事物,另一个是技术? *我试图避免在这里使用“方法”的不明确性 – Ziggy 2009-03-01 22:33:25
指针肯定是一种数据类型。然而,在C++(大多数C人最终使用)中,有一种称为参考的数据类型。这是一个问题,因为在C++中实际上有两种“通过引用传递”的方式,通过实际引用和通过指针。所以“通过参考”是一种方法。 – Uri 2009-03-01 23:14:55