链表添加函数中为什么要用指向链表指针的指针

读剑指offer的时候没有理解,网上有个blog说的特别好,我总结一下:
(源代码在此)

#include <iostream>
#include <string>
using namespace std;
 
struct ListNode
{
	int val;
	ListNode* next;
};
 
void AddToTail(ListNode** pHead, int value);
 
int main() {
	// TODO
	ListNode* head = NULL;
	AddToTail(head, 10);
	if (head != NULL) {
		cout << head->val << endl;
	}
	else {
		cout << "head is NULL.." << endl;
	}
	
}
 
void AddToTail(ListNode** pHead, int value) {
	ListNode* pNew = new ListNode();
	pNew->val = value;
	pNew->next = NULL;
 
	if (pHead == NULL) {
		pHead = pNew;
	}
	else {
		ListNode* p = pHead;
		while (p->next != NULL) {
			p = p->next;
		}
		p->next = pNew;
	}
}
  • 假设int a,作为参数传入的时候没被修改,所以需要用指向a的指针,那么应该也可以理解,指针变量pHead作为参数传入的时候被修改无效,因此需要用指向pHead的指针,只不过pHead本身就是一个指针了,所以才存在有指针的指针看起来稍微复杂一点的说法。因为,指向a的指针作为参数传入进去时,如果你对它进行修改,其实也是无效的,但是修改指针指向的内容的修改是有效的,也即,(&a)对a取地址得到的指针传入进去之后,此时你修改这个指针也是没有什么实际作用的,原因我等下会说。但是,你修改指针指向的内容这就有效了,因此通常我们在函数体内是修改对指针取内容后的内存,即*(&a)。所以,你对指针pHead的修改时无效的,只有对指向pHead的指针指向的内容(很绕吧,其实就是pHead),这时候才是有效的,因此AddToTail的第一个参数必须用指针的指针。

  • 现在来说说为什么对值传参在函数体内的修改无效。因为a传进去的时候会被复制了一份copy,此后的修改都是在临时变量copy上,出了函数体copy被销毁,a还是原来的a,根本就没被修改过,所以才会值传参对变量的修改无效。要使得对a的修改有效,一方面是传入a的地址,也就是对指向a的指针作为值传参(反正修改的不是a的指针,修改了也无所谓,反正只是修改a的指针的copy),此时a的指针的copy指向的内容也是a,因此对copy指向的内容修改会导致a的内容也被修改,check!

  • 另外一种方式就是引用传参,引用传参往往要比值传参高效,因为它是直接将a作为参数传入进去,而少了对a进行复制这部分的开销,既然传入进去的是a,那么对a的修改肯定也生效。

为了验证,原作者改成了引用传参的代码,并且验证成功

#include <iostream>
#include <string>
using namespace std;
 
struct ListNode
{
	int val;
	ListNode* next;
};
 
void AddToTail(ListNode* &pHead, int value);
 
int main() {
	// TODO
	ListNode* head = NULL;
	AddToTail(head, 10);
	if (head != NULL) {
		cout << head->val << endl;
	}
	else {
		cout << "head is NULL.." << endl;
	}
	
}
 
void AddToTail(ListNode* &pHead, int value) {
	ListNode* pNew = new ListNode();
	pNew->val = value;
	pNew->next = NULL;
 
	if (pHead == NULL) {
		pHead = pNew;
	}
	else {
		ListNode* p = pHead;
		while (p->next != NULL) {
			p = p->next;
		}
		p->next = pNew;
	}
}

链表添加函数中为什么要用指向链表指针的指针


我想,这也是能二维甚至多维指针存在的意义之一吧。