我只是C ++的初学者,今天,当我们学习链表时,我的老师向我们展示了如何从链表的最前面删除。问题是我不明白为什么要删除指针p,即静态内存不能仅使用第二个代码使用动态内存指针(temp)来完成吗? Head是Node类型对象的动态内存指针
//My teacher code
template <class T>
void DeleteFront(Node<T>* & head)
{
// save the address of node to be deleted
Node<T> *p = head;
// make sure list is not empty
if (head != NULL)
{
// move head to second node and delete original
head = head->NextNode();
delete p;//I didn't understand this line because our p declaration is static
}
}
//My suggestion
template <class T>
void DeleteFront(Node<T>* & head)
{
// save the address of node to temporary dynamic pointer
Node<T> *temp ;
temp=new Node<T>(head);
// make sure list is not empty
if (head != NULL)
{
// move temp to second node which will be showed by head
temp = head->NextNode();
delete head;//delete front item
head=temp;//assign the address of second node to head
}
}
答案 0 :(得分:0)
p未声明为静态。实际上,这是一个局部变量。静态变量只能在类范围内声明,并用关键字with(df, tapply(numbers, levels, FUN = mean))
# A B C D E
#1.390202 1.541655 2.086605 2.377122 1.663159
标记。
静态变量是可以独立于任何对象访问的变量,并且对于类本身有效,对任何对象都具有相同的值,甚至没有任何对象也是如此。事实并非如此,这是一个非常普通的局部变量,它位于堆栈上并保存指向Node对象的指针。
当您对该指针调用delete时,您将删除指针所指向的内容,而不是堆栈本身上的指针对象。指针本身当然也有一个地址,您可以通过static
获得该地址,并且可以将其保存到&p
变量中。虽然没有必要这样做。在堆栈上的对象上调用delete无效。
现在有关代码:
您正在使用以下方式创建新节点
Node<T>**
这不仅不必要,而且实际上您正在泄漏内存,因为您覆盖了指针值或不调用Node<T> *temp ;
temp=new Node<T>(head);
退出了函数。
至少在指针超出范围(例如函数的末尾)时,每个新函数都应具有相应的删除。这条线是完全多余的。初始化指针的更好方法是:
delete
除此之外,您的代码执行相同的操作。您的老师将要删除的内容保存到p中,该方法可以正常工作,但看起来并不直观,而您保存要保存的内容(Node<T> *temp = nullptr;
。都可以。
head->NextNode()
也是一个函数,应使用小写字母。函数的名称也应暗示其作用。尽管在这种情况下这很容易知道,但NextNode实际上不是动词/动作。 NextNode()
是个好名字。
要改进老师的代码,可以将p的声明放入if块中,如果列表不为空,则保存getNextNode()
以及堆栈操作,但是我敢肯定编译器会为您做到这一点。
答案 1 :(得分:0)
Node<T> *p = head;
// make sure list is not empty
if (head != NULL)
{
// move head to second node and delete original
head = head->NextNode();
delete p;
}
这部分代码将指针p分配给传递给它的头部。然后,它检查磁头是否为NULL,如果不是,则在删除p之前将磁头移到下一个节点-这不是静态的。它是本地的,但不是静态的。这样可以从内存中删除原始磁头,并消除了指针悬空时的大部分机会。
Node<T> *temp ;
temp=new Node<T>(head);
if (head != NULL)
{
temp = head->NextNode();
delete head;
head=temp;
}
此代码在将头部分配给临时对象后删除原始头部,然后将该对象传递回头部。它不会删除临时节点对象。这将是一个潜在的悬空参考,因为头部已通过地址传递,并且在被temp保持时,原始地址从未被删除。