您对 C、C++ 和 Java 中的指针、引用和句柄有啥深刻的理解?

Posted

技术标签:

【中文标题】您对 C、C++ 和 Java 中的指针、引用和句柄有啥深刻的理解?【英文标题】:What's your deep comprehension of pointer,reference and Handle in C,C++ and Java?您对 C、C++ 和 Java 中的指针、引用和句柄有什么深刻的理解? 【发布时间】:2009-09-17 04:41:57 【问题描述】:

你对 C、C++ 和 Java 中的指针、引用和句柄有什么深刻的理解?

我们通常在指定语言级别考虑指针,引用和句柄,像我这样的新手很容易混淆。

其实java中的所有这些概念,只是对指针的一种封装。 所有的指针只是主存地址的一个封装。 所以所有这些,只是一个封装诡计。

以上都是我个人的一瞥。你的理解是什么?

欢迎与我分享。

【问题讨论】:

句柄不是 C++ 或 Java 中的语言结构。它只是 API 提供的不透明标识符的名称,用于该 API 中的进一步调用。 你的意思是Handle实际上是一组指针? @Cong:也许是,也许不是。它是不透明的,所以你不知道。 句柄正是我所说的。 API 提供的用于在该 API 中进一步使用的东西。虽然它可能在给定版本的 API 上以给定方式实现,但使用实现细节是非常糟糕的,因为实现可能会改变,然后破坏您的应用程序。 【参考方案1】:

每种语言在这方面都有差异。在 C 中,只有指针是保存内存地址的变量。在 C 中,您可以使用指针算法在内存中移动,如果您有一个数组,您可以获得指向第一个元素的指针并通过递增指针来导航内存。

Java 引用类似于指针,因为它们指向内存中的某个位置,但您不能对它们使用指针算法。只允许分配。请注意,引用不是对象,而是访问对象的一种方式。这可以从参数传递语义中看出:对象不是通过引用传递的,引用是通过值传递的:

public static void swap( Object o1, Object o2 )

   Object tmp = o1;
   o1 = o2;
   o2 = tmp;

前一段代码是一个复杂的空操作。对两个对象的引用是按值传递的,它们在方法内部被玩弄,从调用者的角度来看没有任何事情发生:真实的对象不会发生任何变化,调用者对这些对象的引用也不会发生任何变化。也就是说,如果调用是 swap(ref1, ref2),系统会将引用复制到 o1 和 o2 中,这些副本在方法内更改,但调用方变量 ref1 和 ref2 在方法调用后将保持不变。

在 C++ 中,您有两个概念:指针与 C 指针相同并且接近 Java 引用,而 C++ 引用是它们所引用对象的别名。 C++ 引用只能在构造中使用一个对象/数据元素初始化,然后使用原始对象和引用完全相同。除了引用不持有资源的事实,因此当引用超出范围时不会调用析构函数,如果引用的对象被销毁,引用也不会通知,对于所有其他用途,这两个名称是相同的元素.

template <typename T>
void swap( T & a, T & b )

   T tmp( a );
   a = b;
   b = tmp;

上面的 C++ 代码与 Java 版本的不同之处在于它确实改变了调用者对象。如果调用者使用 swap( var1, var2 ),则引用将绑定到这些变量,而 var1 和 var2 会受到更改。调用后,var1 和 var2 的值实际上是交换的。

句柄处于不同的级别,它们不是语言构造,而是库提供的标记,以便您稍后可以引用库内部管理的某些资源。最常见的情况是整数句柄,它们是资源表中的 id(或偏移量),但我已经看到字符串用作句柄。由库内部决定什么是处理程序(指针、整数、字符串或更复杂的数据结构)。句柄是不透明的,唯一合理的用途是存储它们,然后将其作为其他函数签名的一部分返回给同一个库。

【讨论】:

+1。这实际上是迄今为止最正确的答案,至少就问题的“指针”与“参考”部分而言。 这个答案很好,如果dribeas对“Handle”发表一些意见会很棒。谢谢大家。 句柄处于不同的级别,它们不是语言结构,而是库提供的令牌,以便您以后可以引用库内部管理的某些资源。最常见的情况是整数句柄,它们是资源表中的 id(或偏移量)。对于句柄,由库内部决定什么是处理程序(指针、整数或更复杂的数据结构) 什么,没有 void swap(T*& a, T*& b)? @Jherico: :) 我会这样写,但事实是编译器可以为您做到这一点:如果这是参数的类型,它将推断类型是指针。除非您想更改语义,否则无需为指针引用提供专门化。【参考方案2】:

在 C++ 中,指针是一个指向内存位置的变量。您可以通过取消引用指针来访问存储在那里的对象或数据。引用只是一个指针,它与指针有两个区别。首先,一旦引用被初始化,您就无法更改引用指向的内容。其次,取消引用语义被删除,因此您可以访问引用,就好像它是在堆栈上分配的对象,而不是在使用 new 的堆上。

在 Java 中,没有指针,只有引用。您使用的每个对象都是对堆上分配的对象的引用。缺点是你不能做指针数学技巧。这也是好处。

编辑: 正如 cmets 中所指出的,Java 引用与 C++ 引用的不同之处在于它可以在初始化后重新分配。它们仍然被语言规范称为“引用类型”,但在行为上它们就像指针一样能够被重新分配和传递给函数,但取消引用它们的语义看起来像 C++ 中的非指针访问。

【讨论】:

"首先,一旦引用被初始化,您就无法更改引用指向的内容。" String str1=new String("改变我"); //初始化 str1 str1="另一个值"; //一旦引用被初始化,这是否会改变str1的引用点。 虽然您说“在 Java 中没有指针,只有引用”是正确的,但您需要澄清 Java 所谓的“引用”与 C++ 所说的“引用”完全不同。 Java 所称的引用更像 C++ 所称的指针。

以上是关于您对 C、C++ 和 Java 中的指针、引用和句柄有啥深刻的理解?的主要内容,如果未能解决你的问题,请参考以下文章

java数组小结

C ++中的指针和引用之间是不是存在任何开销差异[重复]

C++ 指针、引用和函数调用

如何通过JNI将java中的对象的地址赋值给c++指针变量

C语言中取地址跟C++中的引用是一个意思吗?

对比 C++ 和 Python,谈谈指针与引用