为什么C++对链表中的下一个节点使用指针,而像 C# 或 Java 这样的语言只使用类 Node 的名称?

Why C++ uses pointer for next node in linked list, but langauges like C# or Java use just the name of the class Node?

本文关键字:语言 Java Node 而像 链表 C++ 下一个 节点 为什么 指针      更新时间:2023-10-16

C++中的大多数链表实现都是这样的,指针引用将用作"next"节点的类型

class Node {
public:
int data;
Node* next;
}

但是对于像C#,Java和Python这样的语言,为什么不直接使用指针呢?我只能看到这种实现:

// C#
class Node {
int data;
Node next;
}
// Java
class Node {
int data;
Node next;
}

潜在的区别是什么?当然Java不支持指针,但是c#呢?

CPP的Node*相当于Java的Node,我很确定C#的Node也是如此。在Java中,所有原语都是直接值。基元是intlongshortbytechardoublefloatboolean。这些是按值直接传递的:如果你调用一个传递5的方法,5 被推到堆栈上。如果调用的方法更改了其值,则调用方无法分辨。

但是除了硬编码的原语列表之外,所有其他类型都称为引用,它只是指针的java-ese - 除了在java中,你不能做指针算术。你不能要求"内存位置比这个对象所在的位置高5",就像你在C中所做的那样。

这里有一个简单的例子:

class Example {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Hello!");
System.out.println(list);
example1(list);
System.out.println(list);
example2(list);
System.out.println(list);
}
static void example1(List<String> in) {
list.add("World!");
}
static void example2(List<String> in) {
in = new ArrayList<String>();
in.add("Bye!");
}
}

这将打印:

[Hello!]
[Hello!, World!]
[Hello!, World!]

example1 从不更改变量(引用(,它只是"取消引用它"(跟随指针(,因此您所做的更改会在调用者中观察到。

但是 example2 对 main 的列表变量没有影响:它重新分配变量(创建一个新对象,然后更新其引用以指向这个新对象(。 example1 的列表不会更改;它的指针不会改变。

这就像藏宝图:每个人都有藏宝图的副本,但没有宝藏的副本。in.add就像:"按照地图,打开宝箱,放一个新物品"。in = new ArrayList是:"制作一个新的宝箱,把它埋在沙子里,把这张藏宝图抹掉,现在在上面写下这个新埋的宝箱的位置"。如果我有你的地图副本,如果你跟随你的副本并添加到宝藏中,那么如果我稍后按照我的地图,我会看到它。但是,如果你制作了一张全新的地图,那么你在新地点对宝藏所做的一切都不会被我注意到。

这与C++的行为相符。至少,对于Node*.不适合Node.

潜在的区别是什么?

可能根本没有。在机器代码级别,每个节点都包含链中下一个节点的地址。

相反,问题是关于语言如何在源代码中表示对象。写成Foo bar的变量声明(例如(将是Foo类型的实际实例,还是获取(句柄、指针、引用(实际实例的一种方式。 如果它是实际实例,您的语言可能还需要一些语法来描述不是实例,而是获取实例的方式。 也许不止一种方式(Foo*Foo&C++(。

不同方法的可能性是我们拥有不同编程语言的原因之一。

在C++中,变量(对象(可以通过三种方式传递:

  • 按值
  • 通过指针
  • 通过引用

(它们实际上都是按值传递的,但非常具体的一个(

例如,在Java中,对象总是通过引用传递,而原语则通过值传递。Java 中没有指针或显式引用。

C++当您不再需要某个对象时,您需要使用delete将其删除。在Java中,你只需要替换变量,或者只是不使用它 - GB会为你删除它。

阅读了已发布的答案以及与参考文献和指针相关的其他堆栈溢出内容后,例如C++参考与 C# 参考

这对我来说更有意义,

  • C# 引用是托管引用。但在C++没有这样的 管理环境,因此我们需要分配和谨慎 取消分配内存。在 C# 中,这将由 气相色谱。因此,建议尽可能使用引用,而不是 比直接使用指针。

  • 与C++指针类似,C# 也可以保存空值。 C++指针保持 内存位置的地址,C# 引用保存 内存中的另一个对象。

  • 在 C# 中,我们只能在不安全的范围内使用指针,而在 Java 中没有这样的指针概念。

考虑到所有这些,对于在托管环境中执行的编程语言,我们可以使用引用而不是指针。

如果这个答案可以进一步改进,请随意编辑!