在leetcode刷题时,有一个链表加法的问题,我用指针引用技术减少了代码冗余。
原题==>Add Two Numbers
题目比较简单,在函数中我不想修改参数指针l1,l2,所以在3个地方用到了创建新节点,并插入到结果链表尾部:
对应着下面代码的1,2,3位置的insert()函数调用,很明显代码冗余,所以剥离出一个insert函数。我写的第一个版本的insert函数是
void insert(ListNode *head, ListNode *p, int value, int &r;);
leetcode上提交是Wrong Answer, 实际输出为空,也就是说addTwoNumbers()返回了个空指针。 我很快定位到了insert函数的两个指针参数问题,ListNode head 这种格式的参数在函数中只能通过 *head =x;来修改head指针所指向的内存中的值, 不能修改head本身的值,而insert函数中我恰恰修改了指针本身的值(head=p=node),解决方法就是将指针参数改成指针引用参数:
void insert(ListNode* &head;, ListNode* &p;, int value, int &r;)
改成下面形式就更好理解了
typedef ListNode* ListNodePtr;
void insert(ListNodePtr &head;, ListNodePtr &p;, int value, int &r;)
1 struct ListNode {
2 int val;
3 ListNode *next;
4 ListNode(int x) : val(x), next(NULL) {}
5 };
6
7 class Solution {
8 public:
9
10 void insert(ListNode* &head, ListNode* &p, int value, int &r)
11 {
12 ListNode *node = new ListNode(value % 10);
13 r = value / 10;
14 if (!p)
15 {
16 head = p = node;
17 }
18 else
19 {
20 p->next = node;
21 p = p->next;
22 }
23 }
24
25 ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
26 ListNode *head = NULL;
27 ListNode *p=head;
28 ListNode *p1 = l1;
29 ListNode *p2 = l2;
30 ListNode *pt = NULL;
31 int r = 0;
32 int s = 0;
33 //1
34 for (; p1 && p2; p1 = p1->next, p2 = p2->next)
35 {
36 s = r + p1->val + p2->val;
37 insert(head, p, s, r);
38 }
39 //2
40 if (p1)
41 {
42 pt = p1;
43 }
44 else
45 {
46 pt = p2;
47 }
48 for (; pt; pt = pt->next)
49 {
50 s = r + pt->val;
51 insert(head, p, s, r);
52 }
53 //3
54 if (r > 0)
55 {
56 insert(head, p, r, r);
57 }
58 return head;
59 }
60 };
将指针看作一种数据类型
int*
char*
...
如果看着还是不顺眼,就用typedef定义指针类型
typedef int* int_ptr;
typedef char* char_ptr;
...
普通的数据类型引用格式是
int &
char &
...
指针引用和它们一样
int_ptr &
char_ptr &
...
等价于
int *&
char *&
...
引用的重要用途是函数传参,避免参数拷贝,可以直接对源数据进行修改,在函数调用结束后,保留修改。下面两种方式的区别:
1 void func1(int *p)
2 {
3 *p = 10;
4 }
5 void func2(int &p);
6 {
7 p = 10;
8 }
9
10 int main()
11 {
12 int x = 1000;
13 int *p = &x;
14 func1(p); //<==>func1(&x;);
15 func2(x);
16 }
从上面代码可以看出,指针传参,在函数内部修改是的指针所指向的内容,不是指针本身;引用传参修改的就是引用的数据变量。
那么问题来了,如果我们要修改指针本身呢,就像第一部分中,要通过一个函数修改链表指针参数。
答案很简单,
int &x; 修改x的值
char &ch; 修改ch的值
...
int_ptr &p; 也就会修改p的值
int_ptr &p; 等价于 int *&p;