C++ 取消分配指向保留嵌套变量内存地址的结构的指针 模板 T&List::popFront() { if(head==NULL) throw std::underflow_错误(“列表错误:没有可用的头节点\n”); 如果(尾部==头部) tail=NULL; T项目=头->项目; 头部=头部->下一步; 退货项目; }

C++ 取消分配指向保留嵌套变量内存地址的结构的指针 模板 T&List::popFront() { if(head==NULL) throw std::underflow_错误(“列表错误:没有可用的头节点\n”); 如果(尾部==头部) tail=NULL; T项目=头->项目; 头部=头部->下一步; 退货项目; },c++,pointers,memory-leaks,nested,C++,Pointers,Memory Leaks,Nested,我有一个递归结构ListNode,其中包含以下字段: template<typename T> T& List<T>::popFront() { if (head == NULL) throw std::underflow_error("List error: no head node available\n"); if (tail == head) tail = NULL; T item = head-&g

我有一个递归结构ListNode,其中包含以下字段:

template<typename T>
T& List<T>::popFront()
{
    if (head == NULL)
        throw std::underflow_error("List error: no head node available\n");
    if (tail == head)
        tail = NULL;
    T item = head->item;
    head = head->next;
    return item;
}
模板
结构列表节点{
T项;
ListNode*下一步;
...
}
问题是,我想在popFront过程之后释放一个head节点,但由于所有嵌套节点都间接指向同一地址,它们的地址也会从堆中消失。现在,正如你在上面看到的,我只是把一个头节点的指针地址改成下一个,我相信这会导致内存泄漏


我不排除这种方法和我的假设是绝对错误的。请考虑执行这种任务的最有效的方法,如果这种分配确实是必要的。

< P>当你弹出头,在删除它之前,抓住下一个指针,使它的头。< /P>
template <typename T>
struct ListNode {
    T item;
    ListNode* next;
    ...
}
模板
T List::popFront()
{
if(head==NULL)
抛出std::下溢_错误(“列表错误:没有可用的头节点”);
如果(尾部==头部)
tail=NULL;
T项目=头->项目;
ListNode*next=头部->下一步;//抓取下一步
删除头部;//现在可以安全地删除头部
head=next;//head现在指向next
退货项目;
}
这里需要尾巴吗?当只有一个节点时,为什么不让head的next等于
NULL


编辑:刚刚注意到。您不应该返回对
项的引用,因为我们正在销毁保存它的
列表节点。按值返回。或者,您可以返回
ListNode*
,而不是删除它,但这可能不是您希望
List
界面工作的方式。

当您弹出标题时,在删除它之前,抓住下一个指针并使其成为标题

template <typename T>
struct ListNode {
    T item;
    ListNode* next;
    ...
}
模板
T List::popFront()
{
if(head==NULL)
抛出std::下溢_错误(“列表错误:没有可用的头节点”);
如果(尾部==头部)
tail=NULL;
T项目=头->项目;
ListNode*next=头部->下一步;//抓取下一步
删除头部;//现在可以安全地删除头部
head=next;//head现在指向next
退货项目;
}
这里需要尾巴吗?当只有一个节点时,为什么不让head的next等于
NULL


编辑:刚刚注意到。您不应该返回对
项的引用,因为我们正在销毁保存它的
列表节点。按值返回。或者,您可以返回
ListNode*
,而不是删除它,但这可能不是您希望
List
的界面工作的方式。

这里有几个问题

template<typename T>
T List<T>::popFront()
{
    if (head == NULL)
        throw std::underflow_error("List error: no head node available");
    if (tail == head)
        tail = NULL;
    T item = head->item;
    ListNode *next = head->next;    // Grab next
    delete head;                    // Now it is safe to delete head
    head = next;                    // Head now points to next
    return item;
}
模板
T&List::popFront()
{
if(head==NULL)
throw std::underflow_错误(“列表错误:没有可用的头节点\n”);
如果(尾部==头部)
tail=NULL;
T项目=头->项目;
head=head->next;//内存泄漏,您刚刚丢失了指向head项的唯一指针
return item;//返回对堆栈变量的引用,未定义的行为
}
我建议您将签名更改为按值返回,这样您就可以返回一个本地元素并在堆中释放该元素

template<typename T>
T& List<T>::popFront()
{
    if (head == NULL)
        throw std::underflow_error("List error: no head node available\n");
    if (tail == head)
        tail = NULL;
    T item = head->item;
    head = head->next; //Memory leak, you just lost your only pointer to the head item
    return item; //Returning reference to stack variable, undefined behavior
}
模板
T List::popFront()
{
if(head==NULL)
throw std::underflow_错误(“列表错误:没有可用的头节点\n”);
如果(尾部==头部)
tail=NULL;
T项目=头->项目;
ListNode*old_head=head;//保留此项以便解除分配
头部=头部->下一步;
删除旧头;//取消分配旧头
return item;//按值返回
}
当然,您可以采用和的行为,并分别使用不同的访问和弹出方法

根据签名,
front()
返回一个引用,如果
T
是一个较重的对象,则该引用的效率要高得多


当然,这都是假设你是为了学术目的。否则,请使用
std::list
或类似的标准库容器。

这里有几个问题

template<typename T>
T List<T>::popFront()
{
    if (head == NULL)
        throw std::underflow_error("List error: no head node available");
    if (tail == head)
        tail = NULL;
    T item = head->item;
    ListNode *next = head->next;    // Grab next
    delete head;                    // Now it is safe to delete head
    head = next;                    // Head now points to next
    return item;
}
模板
T&List::popFront()
{
if(head==NULL)
throw std::underflow_错误(“列表错误:没有可用的头节点\n”);
如果(尾部==头部)
tail=NULL;
T项=头->项目;
head=head->next;//内存泄漏,您刚刚丢失了指向head项的唯一指针
return item;//返回对堆栈变量的引用,未定义的行为
}
我建议您将签名更改为按值返回,这样您就可以返回一个本地元素并在堆中释放该元素

template<typename T>
T& List<T>::popFront()
{
    if (head == NULL)
        throw std::underflow_error("List error: no head node available\n");
    if (tail == head)
        tail = NULL;
    T item = head->item;
    head = head->next; //Memory leak, you just lost your only pointer to the head item
    return item; //Returning reference to stack variable, undefined behavior
}
模板
T List::popFront()
{
if(head==NULL)
抛出std::underflow\u错误(“列表错误:没有可用的头节点\n”);
如果(尾部==头部)
tail=NULL;
T项目=头->项目;
ListNode*old_head=head;//保留此项以便解除分配
头部=头部->下一步;
删除旧头;//取消分配旧头
return item;//按值返回
}
当然,您可以采用和的行为,并分别使用不同的访问和弹出方法

根据签名,
front()
返回一个引用,如果
T
是一个较重的对象,则该引用的效率要高得多


当然,这都是假设你是为了学术目的。否则,可以使用
std::list
或类似的标准库容器。

返回对本地自动变量的引用。使用返回引用有未定义的行为。@ USER 2079303是的,没有注意到,修复。“请考虑最有效的方式来执行这样的任务”答案是使用经过测试的标准库,所以<代码> STD::列表< /COD>或<代码> STD::它的作者知道什么