如果给出一个列表,并且每个ListNode都被定义为结构:
Struct ListNode
{
int val;
ListNode *next;
//and some constructor
}
我们得到列表的头指针,由ListNode * head表示。 现在,如果我将ListNode * head作为参数传递给函数,例如
int sum(ListNode *head){}
然后我遍历列表而不复制* head。 例如,我做
for(; head!=null; head=head->next)
在调用函数后,* head仍会指向列表的头节点吗?
在Java中,如果我们将ListNode定义为一个类并使用ListNode头进行相同的遍历(不进行复制),那么会发生什么呢?
有人能从内存分配角度说明这一点吗?感谢
注意:由于Java中的List接口,我感到困惑。我认为即使我们将它作为参数传递给函数,也可以更改ArrayList的值。但是在C ++中这不会发生吗?
答案 0 :(得分:1)
在调用函数后,* head仍会指向列表的头节点吗?
是。通过分配给head
,您只需要修改指针,而不是指向的内存。如果您分配到*head
,head->val
等,则会在来电者中观察到该更新。
在Java中,如果我们将ListNode定义为一个类并使用ListNode头进行相同的遍历(不进行复制),那么会发生什么呢?
与C中相同。通过分配给head
,您只需修改引用,而不是引用的内存。
答案 1 :(得分:1)
你说"没有制作副本",这实际上是你答案的关键:当调用该函数时, head
值的副本作为参数传递给它。因此,无论函数内部对其进行任何更改,都不会以任何方式影响调用者的副本。
这被称为"按值传递"。在C ++中,有一种通过引用传递参数的方法:int sum((ListNode *)& head){}
,这种方式声明的函数与调用者具有相同的head
,而不是副本,以及它对它所做的任何更改,将也可以给来电者看。
Java和C没有这种能力,函数总是得到调用者值的副本作为参数,并且不能对调用者看到的任何更改。
答案 2 :(得分:0)
在Java中,head
引用的副本将传递给该函数。但是,由于head
引用的副本仍然是对ListNode的引用,因此您仍然可以成功遍历原始的linkedList。
你提到了:
if I pass ListNode *head as a parameter into a function such as
int sum(ListNode *head){}
and then I traverse the list without making a copy of *head.
是的,这是对的。在Java中,您可以执行相同的操作(遍历列表而不复制头部),因为您正在使用head.
答案 3 :(得分:0)
在C ++中,您将第一个节点的地址从main传递给函数。因此head(在main中)的值不会改变。也就是说,变量 head (在main中) )和 head (在函数中)是两个不同的变量。 head (在函数中)只是在变化。