C++ 指针返回

C++ 指针返回,c++,linked-list,C++,Linked List,我正在解决一个编码挑战。在这个挑战中,我们将得到两个链表(2->4->3)和(5->6->4),我们必须返回它们相加的结果(7->0->8) 虽然我解决了这个问题,但我在谷歌上找到了一个更好的版本: ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) { ListNode preHead(0), *p = &preHead; int extra = 0; while (l1 || l2 || extra) {

我正在解决一个编码挑战。在这个挑战中,我们将得到两个链表(2->4->3)和(5->6->4),我们必须返回它们相加的结果(7->0->8)

虽然我解决了这个问题,但我在谷歌上找到了一个更好的版本:

ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
    ListNode preHead(0), *p = &preHead;
    int extra = 0;
    while (l1 || l2 || extra) {
        int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + extra;
        extra = sum / 10;
        p->next = new ListNode(sum % 10);
        p = p->next;
        l1 = l1 ? l1->next : l1;
        l2 = l2 ? l2->next : l2;
    }
    return preHead.next;
}
但是,我不理解步骤
listnodeprehead(0),*p=&preHead
preHead
的地址存储在指针变量
p
中。换句话说,
p
指向
preHead
。那么,为什么最后会返回
preHead.next
?请注意,此代码确实编译并返回预期的输出

谢谢你的帮助

下面一行:

p->next =new ListNode(sum % 10);
分配返回的新节点


在循环的第一次迭代中,
*p
preHead
相同。以后的迭代会移动
p
,但不会使持有指向添加的第一个新元素的指针的
preHead
无效。

我喜欢将其称为虚拟节点模式。在这里,用户将构造一个未使用的节点,以使插入和查找等操作更容易实现。正如您在函数中所看到的,
p
已经指向一个有效的节点开始,因此无需检查
p
是否为
NULL
,并将其设置为this is true的节点,而只需使用
p->next
附加一个节点。这是可选代码,其中
p
的起始值为
NULL

ListNode* p = nullptr;
ListNode* tail;
while (l1 || l2 || extra) {
    //int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + extra;
    //extra = sum / 10;
    if (p != nullptr) {
        tail->next = new ListNode(sum % 10);
        tail = tail->next;
    } else {
        tail = p = new ListNode(sum % 10);
    }
    //l1 = l1 ? l1->next : l1;
    //l2 = l2 ? l2->next : l2;
}
return p;
我们必须保留一个指向列表末尾的额外指针,以便知道在每次迭代中插入的位置。在第一次插入时,我们必须确保
p
不是空指针

返回
preHead.next
的原因是因为
preHead.next
是插入开始的地方(它是我们要返回的实际链表的头)

那么,为什么最后会返回
preHead.next

因为
addTwoNumber
返回指针,但
preHead
是堆栈变量(即临时变量);将临时引用作为指针返回以在以后取消引用是未定义的行为


但是,
preHead.next
是一个堆分配的变量,可以在需要时正确地取消引用。

循环正在构造一个新的链表,并使用
preHead.next
指向该列表中的第一个节点
p
只是它用来跟踪当前节点的指针(在循环之前,它指向
preHead
,但在循环中指向列表中的最后一个节点。顺便说一句,该代码过于神秘,因此我不会将其描述为一个特别好的解决方案。谢谢!如果
preHead->next
指向开头的第一个节点,那么我们不是在增加它吗(通过
p=p->next
)?它如何指向列表末尾的标题?
p
是一个与
preHead
不同的变量。虽然初始化为
和preHead
,但赋值
p=p->next
会更改
p
(使其指向列表中的下一个对象)。它不会影响更改
预读
。是的,我理解。但是,我的问题是,
如何预读。下一步
指向正在创建的新链表?