数据结构新手,最近学习Listnode。有问题。 定义一个ListNode:
struct ListNode
{
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
void AddToTail(ListNode** head, int value)
{
ListNode* nlist = new ListNode(value);
if(*head == NULL)
{
*head = nlist;
}
else
{
ListNode* p = *head;
while(p->next != NULL)
{
p = p->next;
}
p->next = nlist;
}
// No need to delete nlist, since the memory allocated by it is already organized by the ListNode.
}
int main()
{
ListNode* L = new ListNode(5);
AddToTail(&L, 10);
ListNode* p = L;
while(p->next != NULL)
{
p = p->next;
}
printf("Final value is %d.\n", p->val);
delete L;
}
到现在为止,一切似乎还好吧?我想知道如果不在堆中分配ListNode内存,那意味着我不使用new,而我使用ListNode L;
然后手动对其进行初始化。它的内存现在已堆叠。添加到它的尾部在堆内存中。我现在如何删除堆内存。看来ListNode内存的一部分在堆栈中,而一部分在堆中?我正确理解了吗?
答案 0 :(得分:4)
是的,L
是否动态分配并不重要。那就这样。实际上,这里没有理由动态分配它。
重要的是它管理的节点的所有权和生存期。这些是动态分配的,因此您需要在ListNode
内部使用一个析构函数,以取消链接并取消分配节点。
“混合”存储期限没有什么问题-例如,这就是您每次实例化std::vector<int>
时所做的事情。您只需要确保所有拥有动态分配的数据都具有清除自身的功能。
答案 1 :(得分:1)
您需要像这样的删除功能
void DeleteList(ListNode** head)
{
ListNode* p = *head;
while(p != NULL)
{
ListNode *t = p->next;
delete p;
p = t;
}
}
// and call it in main:
printf("Final value is %d.\n", p->val);
DeleteList(&L);
但是最好立即在一个特殊的类中定义所有这些操作,例如List:
class List
{
private:
ListNode *head;
public:
List() : head(NULL){}
~List() { Clear(); }
void AddToTail(int value);
void Clear();
};
void List::AddToTail(int value)
{
ListNode* nlist = new ListNode(value);
if(head == NULL)
{
head = nlist;
}
else
{
ListNode* p = head;
while(p->next != NULL)
{
p = p->next;
}
p->next = nlist;
}
}
void List::Clear()
{
ListNode* p = head;
while(p != NULL)
{
ListNode *t = p->next;
delete p;
p = t;
}
head = NULL;
}
并像这样使用它:
List lst;
lst.AddToTail(5);
lst.AddToTail(10);
lst.AddToTail(20);
lst.AddToTail(30);
lst.Clear();