C++ c+中的内存分配+;使用分离函数
我有cplusplus代码来制作单链表C++ c+中的内存分配+;使用分离函数,c++,pointers,memory,dynamic,reference,C++,Pointers,Memory,Dynamic,Reference,我有cplusplus代码来制作单链表 struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; 使用以下功能: static void push_l
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
使用以下功能:
static void push_list(struct ListNode*& _head, int _val)
{
if (NULL == _head)
_head = new ListNode(_val);
else{
ListNode* tmp = _head->next;
while (tmp != NULL)
tmp = tmp->next;
tmp = new ListNode(_val);
}
}
但是,它只分配一个元素,head->next保持为空
函数的调用如下所示:
static void MakeList(void)
{
ListNode* l1 = NULL;
push_list(l1, 1);
push_list(l1, 2);
push_list(l1, 3);
push_list(l1, 4);
}
您的推送列表()
实现错误
当\u head
为空时,您将创建一个新节点并将其分配给\u head
。好的,到目前为止
但是在随后的调用中,当\u head
不为null时,您将\u head->next
分配给tmp
,并且当列表有1个节点时,\u head->next
将为null。因此,您的虽然循环没有做任何事情,但将tmp
设置为null(即使列表中有多个节点,您的循环最终将到达最后一个节点,并将tmp
设置为其下一个,因此无论是否输入循环tmp
都将始终为null)。然后创建一个新节点,并将其仅分配给tmp
,而不是分配给列表中最后一个节点的next
字段。因此,您泄漏了新节点,\u head->next
在下次调用push\u list()
时保持空值,从而一次又一次地导致相同的问题
要解决此问题,需要调整循环以查找列表中的最后一个节点,然后可以将新节点分配给最后一个节点的next
字段,例如:
静态无效推送列表(ListNode*&\u head,int\u val)
{
如果(!\u头)
_head=新的ListNode(_val);
否则{
ListNode*tmp=\u head;//下一步!
而(tmp->next){//next;
}
//tmp现在指向最后一个节点,而不是null!
tmp->next=新列表节点(_val);
}
}
push_list()
然后可以通过使用稍微不同、更优化的循环策略进一步简化:
静态无效推送列表(ListNode*&\u head,int\u val)
{
ListNode**tmp=&_头;
而(*tmp){
tmp=&(*tmp)->下一步;
}
*tmp=新的ListNode(_val);
}
此循环查找第一个为null的ListNode*
指针,然后为该指针分配一个新节点。这样,您就不必单独处理头部。\u头
本身将为空,或者列表中最后一个节点的下一个
字段将为空。第一个可用的空值是您要插入新节点的位置。您的推送列表()
实现错误
当\u head
为空时,您将创建一个新节点并将其分配给\u head
。好的,到目前为止
但是在随后的调用中,当\u head
不为null时,您将\u head->next
分配给tmp
,并且当列表有1个节点时,\u head->next
将为null。因此,您的虽然循环没有做任何事情,但将tmp
设置为null(即使列表中有多个节点,您的循环最终将到达最后一个节点,并将tmp
设置为其下一个,因此无论是否输入循环tmp
都将始终为null)。然后创建一个新节点,并将其仅分配给tmp
,而不是分配给列表中最后一个节点的next
字段。因此,您泄漏了新节点,\u head->next
在下次调用push\u list()
时保持空值,从而一次又一次地导致相同的问题
要解决此问题,需要调整循环以查找列表中的最后一个节点,然后可以将新节点分配给最后一个节点的next
字段,例如:
静态无效推送列表(ListNode*&\u head,int\u val)
{
如果(!\u头)
_head=新的ListNode(_val);
否则{
ListNode*tmp=\u head;//下一步!
而(tmp->next){//next;
}
//tmp现在指向最后一个节点,而不是null!
tmp->next=新列表节点(_val);
}
}
push_list()
然后可以通过使用稍微不同、更优化的循环策略进一步简化:
静态无效推送列表(ListNode*&\u head,int\u val)
{
ListNode**tmp=&_头;
而(*tmp){
tmp=&(*tmp)->下一步;
}
*tmp=新的ListNode(_val);
}
此循环查找第一个为null的ListNode*
指针,然后为该指针分配一个新节点。这样,您就不必单独处理头部。\u头
本身将为空,或者列表中最后一个节点的下一个
字段将为空。第一个可用的空值是您要插入新节点的位置。您应该使用调试器逐步完成代码。这将有助于您理解为什么代码与预期不符当执行代码>时,tmp
仅在列表末尾包含NULL
指针的副本。更改此副本的值不会更改存储在链接列表末尾的原始值。因此,您可能希望使tmp
成为双指针或指针的引用,就像您使用\u head
参数一样;std::vector.在旁注中,您不应该将NULL
和nullptr
混合在一起。因为您有可用的NULL ptr
,所以应该在任何地方都使用它,而不是使用NULL
nullptr
被发明来代替NULL。您应该使用调试器逐步检查代码。这将有助于您理解为什么代码与预期不符当执行代码>时,tmp
仅在列表末尾包含NULL
指针的副本。更改此副本的值不会更改存储在链接列表末尾的原始值。因此,您可能希望使tmp
成为双指针或引用