在这个例子中,我不明白为什么无法动态分配列表的第一个元素。 我理解解决方案很糟糕,因为我将丢失指向“a”的指针,它将悬空。我不明白的是为什么在这种情况下我的函数返回一个空列表。
我按要求简化了示例:
ListNode* createList() {
//Why not - ListNode* a = new ListNode(0); ?
ListNode list(0); ListNode * a = &list;
for(int i=0; i < 5; i++){
a->next = new ListNode(0);
a = a->next;
}
//return a->next;
return list.next;
}
答案 0 :(得分:1)
我修改了您的代码,以便动态分配第一个元素。
建议的解决方案存在的问题是,当 a 到达列表末尾时,它会将指针返回到列表的末尾(因此返回空列表)。
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if (l1 == NULL && l2 == NULL) return NULL;
int carry = 0, sum = 0;
ListNode* a = new ListNode(0);
ListNode* head = a;
while(l1 || l2 || carry){
sum = carry;
if (l1 != NULL) sum+=l1->val;
if (l2 != NULL) sum+=l2->val;
carry = sum/10;
a->next = new ListNode(sum % 10);
a = a->next;
l1 = (l1 == NULL) ? NULL : l1->next;
l2 = (l2 == NULL) ? NULL : l2->next;
}
return head->next;
}
希望它有所帮助。
答案 1 :(得分:1)
返回a->next
失败是因为
a = a->next;
在创建列表时遍历列表,因此a
始终指向列表中的最后一个节点。完成构建列表后
return a->next;
a
仍然是列表中的最后一个节点,next
可能是NULL
或nullptr
。如果它不是,你就会得到一个巨大的爆炸虫。没有返回列表,因为没有更多列表要返回,此时您已经丢失了列表的开头。糟糕!
另一方面,
return list.next;
在您创建的虚拟占位符节点之后返回节点,这是您在虚拟节点上构建的列表。由于list
是一个局部变量,因此它具有自动存储持续时间,并在超出范围时为您清理。它所指向的ListNode
链都是动态分配的,可以安全返回。
附录:
在您删除的代码中,使用
动态分配a
ListNode* a = new ListNode(0);
表示在函数结束时a
需要清理,如你所指出的那样,虽然这不是一个悬空指针,但它被称为泄漏。
你可以用
来挽救它ListNode* a = new ListNode(0);
ListNode* start = a;
以后
return start->next;
但是使用list
创建的自动版本不需要清理,是更好的选择,因为可能会出错。
更好的是,根本没有虚拟节点,只保留指向第一个创建节点的指针,但那是另一个时间的故事。