![](/img/trans.png)
[英]handling refrence to pointers/double pointers using SWIG [C++ to Java]
[英]C++ passing pointers by Refrence or Value
考虑以下代码:
#include <iostream>
using namespace std;
struct Node
{
int x;
Node *next;
};
void append(Node* h1, Node* h2)
{
cout << h1 << ":" << h2;
cout << endl;
Node *ptr;
ptr = h1;
while ( ptr->next != NULL)
{
ptr = ptr->next;
}
ptr->next = h2;
}
void insertAtHead(Node* head, int k)
{
Node *tmp = new Node;
tmp -> x = k;
tmp -> next = head;
head = tmp;
}
int main()
{
Node *n1 = new Node;
n1->x = 1;
n1->next = NULL;
Node *n2 = new Node;
n2->x = 2;
n2->next = NULL;
Node *n3 = new Node;
n3->x = 3;
n3->next = n2;
cout << n1 << ":" << n3;
cout << endl;
append(n1,n3);
insertAtHead(n1,4);
while(n1 != NULL)
{
cout << n1->x;
n1 = n1->next;
}
cout << endl;
}
即使我们拥有Node* h1
,append函数仍然有效,但是即使我们拥有相同的Node* head.
insertAtHead也无法正常工作Node* head.
为什么??
我们需要Node* &head
才能使appendAtHead起作用。 为什么?
按值传递表示函数将创建参数的副本,因此它不会更改传递的实际参数,而按引用传递将使您可以修改函数中的参数。 知道这一点,这就是为什么Node* &head
可以工作但Node* head
对于您的insertAtHead()
函数不起作用的原因。
对于append()函数,正在修改它,因为Node* ptr
变量指向h1的地址,这使您可以将下一个值设置为h2(参数设置为n3),而不必设置要传递的参数。参考。 在n1到达append函数之前,它的下一个节点设置为NULL,而在调用append函数之后,现在它将下一个节点设置为n3。 (IMO,我认为您应该给他们使用不同的名称,看到n1,h1,n2,h2等会让人感到困惑。)
原因很简单:
在void insertAtHead(Node * head,int k)的情况下,当按值传递head时,您正在处理实际head的副本,该副本存在于堆栈中,因此在退出函数时会被丢弃。
这就是为什么必须通过引用传递的原因,因此head并不是堆栈上节点的副本,而是您要操作的实际节点。
编辑以回答您的评论:
append之所以有效,是因为您获得了指针的副本,因此可以修改其指向的下层数据,但是您无法更改所获得的实际指针,因为它是存在于堆栈中的临时副本。
在函数中附加指针h1不变
在函数insertAtHead中应该更改head,但是要更改局部变量。 您应考虑到参数是函数的局部变量。 因此,退出函数后,所有局部变量均被销毁。
如果函数append处理一个空列表,您将获得相同的效果。 在这种情况下,您必须在函数内部分配磁头,并且磁头的这些更改不会影响原始磁头。
有三种方法可以正确编写这些功能。 每个函数要么返回更新的head,要么必须通过引用或间接通过head指针来传递head。
例如,考虑如果列表为空,即当第一个参数等于NULL时,函数append将如何工作。
void append(Node* h1, Node* h2)
{
cout << h1 << ":" << h2;
cout << endl;
if ( h1 == NULL )
{
h1 = h2;
}
else
{
Node *ptr = h1;
while ( ptr->next != NULL) ptr = ptr->next;
ptr->next = h2;
}
}
在这种情况下,您将看到与函数insertAtHead相同的错误。 函数内部h1的更改不会影响head的原始值。 仅局部变量h1将被更改,然后在退出函数后销毁。 原始变量头将保持与以前相同的旧值。
指针按值传递(您传递指针值的副本-即所指向的内存地址的副本)。
引用是通过引用传递的(即,当函数参数的函数签名中带有&prefix时)。 在这种情况下,如果将引用指向函数内部的其他内容,则当程序流退出函数范围并返回时,原始引用也指向其他内容。
这是Java区别的说明(使用C ++作为能够通过引用传递Java不能做到的示例):
http://blog.aaronshaw.net/2014/02/13/java-is-always-pass-by-value/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.