遇到的问题
刷题的时候,遇到关于链表的操作,忘记给节点分配空间,导致错误。由于指针的使用频率较低,思考良久,秉着实践是检验真理的唯一标准的思想,整理一下关于内存动态分配的问题。
思考
因为链表中每一个节点都是一个指针,如果没有给每一个指针(节点)都申请空间的话,会导致每个指针(节点)都是一样的地址,则会导致错误。
实践
首先看如果没有申请内存空间会导致的错误:
#include <iostream>
#include <stdlib.h>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
int main() {
ListNode *l3 = new ListNode(0);
ListNode *head3 = l3;
for(int i = 1; i < 10; ++i) {
ListNode tmp(i);
l3->next = &tmp;
l3 = &tmp;
cout << l3 << " " << l3->val << " " << "\n";
}
cout << "l3 : ";
while(head3 != NULL && n != 0) {
cout << head3 << " " << head3->val << "\n";
head3 = head3->next;
n--;
}
return 0;
}
我们的初衷是想创建九个节点并且给每个节点赋值。
但是输出结果为:
0x7ffc4cc26850 1
0x7ffc4cc26850 2
0x7ffc4cc26850 3
0x7ffc4cc26850 4
0x7ffc4cc26850 5
0x7ffc4cc26850 6
0x7ffc4cc26850 7
0x7ffc4cc26850 8
0x7ffc4cc26850 9
l3 : 0x1dd1070 0
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
0x7ffc4cc26850 9
除了head3节点是正确的,后面赋值的节点以及节点指向的下一个节点地址都是一样的,说明在循环中,尽管节点指向的值每次会改变之外,定义的节点tmp并没有申请新的内存来存储。就会导致这个链表错误。
正确姿势
#include <iostream>
#include <stdlib.h>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
int main() {
ListNode *l1 = new ListNode(0);
ListNode *l2 = new ListNode(0);
ListNode *head1 = l1;
ListNode *head2 = l2;
for(int i = 1; i < 10; ++i) {
ListNode *tmp = new ListNode(i);
l1->next = tmp;
l1 = tmp;
cout << l1 << " " << l1->val << " " << "\n";
//delete(tmp);
}
cout << endl;
for(int i = 1; i < 10; ++i) {
ListNode *tmp = (ListNode *)malloc(sizeof(ListNode));
tmp->val = i; tmp->next = NULL;
l2->next = tmp;
l2 = tmp;
cout << l2 << " " << l2->val << " " << "\n";
//free(tmp);
}
cout << endl;
cout << "l1 : ";
int n = 20;
while(head1 != NULL && n != 0) {
cout << head1 << " " << head1->val << "\n";
head1 = head1->next;
n--;
}
cout << endl;
cout << "l2 : ";
while(head2 != NULL && n != 20) {
cout << head2 << " " << head2->val << "\n";
head2 = head2->next;
n++;
}
return 0;
}
使用new或者malloc(需要添加头文件<stdlib.h>),但是在申请之后千万不要用delete或者free释放空间,因为这里需要的就是分配空间,如果需要释放,则需要在链表中操作。
输出地址显真相
在输出地址的时候发现
cout << l1 << " " << l2 << " " << l3 << " " << head1 << " "<< head2 << " "<< head3 << endl;
cout << l1->next << " " << l2->next << " " << l3->next << " " << head1->next << " "<< head2->next << " "<< head3->next << endl;
最开始的输出为:
//输出为
0x1dd1030 0x1dd1050 0x1dd1070 0x1dd1030 0x1dd1050 0x1dd1070
0 0 0 0 0 0
每次申请的指针都会递增20个字节,然后就会发现,结构体中int占4个字节,ListNode占16个字节。并且在后面动态的分配内存的时候也会发现依次递增20个字节。
在给三个链表进行赋值操作之后输出为:
//输出为
0x1dd1190 0x1dd12b0 0x7ffc4cc26850 0x1dd1030 0x1dd1050 0x1dd1070
0 0 0x7ffc4cc26850 0x1dd1090 0x1dd11b0 0x7ffc4cc26850
通过这个也能发现,如果没有分配内存,会导致链表出现bug~