C++中的链表实现大多是这样的,一个指针引用将被用作“下一个”节点的类型
class Node {
public:
int data;
Node* next;
}
但是对于像C#,Java和Python这样的语言,为什么不直接使用指针呢? 我只能看到这种实现:
// C#
class Node {
int data;
Node next;
}
// Java
class Node {
int data;
Node next;
}
潜在的区别是什么?
CPP的节点*
相当于Java的节点
,我很确定C#的节点
也是这样。在Java,所有原语都是直接值。原语有int
,long
,short
,byte
,char
,double
,float
和boolean
。这些都是按值直接传递的:如果调用传递5
的
但是除了那些硬编码的原语列表之外,所有其他类型都被称为引用,这只是Java语中的指针--除了在Java语中,你不能做指针算术。 一点也不。 你不能像在C语言中那样要求“内存位置比这个对象所在的位置高5个”。
下面是一个微不足道的例子:
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的list变量没有影响:它重新分配变量(生成一个新对象,然后更新它的引用以指向这个新对象)。 example1的列表没有改变; 它的指针不变。
这就像藏宝图:每个人都有藏宝图的副本,但没有藏宝的副本。 in.add
就像:“跟着地图走,打开宝箱,放一个新物品进去”。 在=new ArrayList
中是:“制作一个新的宝箱,把它埋在沙子里,消灭这张藏宝图,现在把这个新埋的宝箱的位置写在上面”。 如果我有你地图的副本,如果你跟随你的副本并添加到宝藏,那么如果我以后跟随我的地图,我会看到的。 但如果你制作了一张全新的地图,那么无论你在新位置对宝藏做了什么,我都不会注意到。
这与C++的行为相匹配。。。。 至少,对于节点*
。 不适用于节点
。
潜在的区别是什么?
可能一点也没有。 在机器代码级别,每个节点包含链中下一个节点的地址。
相反,问题在于语言如何在源代码中表示对象。 以foobar
形式编写的变量声明(例如)将成为foo
类型的实际实例,还是将成为获取(句柄,指针,引用)实际实例的一种方法。 如果是实际的实例,您的语言可能还需要一些语法来描述不是实例而是获取实例的方法。 可能不止一种方式(foo*
,C++中的foo&
)。
不同方法的可能性是我们拥有不同编程语言的一个原因。
在C++中,变量(对象)可以通过三种方式传递:
(都是在现实中通过价值传递,但很具体的一个)
例如,在Java中,对象总是通过引用传递,而基元则通过值传递。 在Java中没有任何指针或明确的参考。
在C++中,当您不再需要一个对象时,需要使用delete
将其移除。 在Java,你只需要替换variable或者只是不使用它-GB会为你移除它。