链表pop_back实现忽略指向nullptr的指针

Linked list pop_back implementation ignores pointer-to-nullptr

本文关键字:nullptr 指针 pop back 实现 链表      更新时间:2023-10-16

假设我的实现中只允许使用newdelete,而不允许使用智能指针。我没有使用sentinel节点。

以下是我对pop_back:的实现

void sLinkedList::pop_back()
{
  if(begin == nullptr)
  {
    std::cerr << "There is nothing to pop." << std::endl;
  }
  else
  {
    node* nodeToDelete = begin;
    while(nodeToDelete->next != nullptr)
    {
      nodeToDelete = nodeToDelete->next;
    }
    delete nodeToDelete;
    nodeToDelete = nullptr;
    --mSize;
  }
}

它所做的是创建一个指向节点nodeToDelete的指针,并遍历整个列表,直到到达最后一个节点(指向nullptr的节点(。然后我删除最后一个节点,将其设置为nullptr,一切都应该很好,因为在此之前的节点(以前是倒数第二个节点(现在指向一个nullptr,标记列表的末尾。

当我按照以下说明运行main时:

int main()
{
  sLinkedList newList;
  std::cout << "Length is " << newList.length() << std::endl;
  newList.print();
  newList.push_front(4);
  std::cout << "Length is " << newList.length() << std:: endl;
  newList.print();
  newList.pop_back();
  std::cout << "Length is " << newList.length() << std::endl;
  newList.print();
}

我得到输出:

Length is 0
The list is empty.
Length is 1
4
Length is 0
4 // should print "There is nothing to pop."

在第一个之后直接添加另一个CCD_ 5得到CCD_。

为什么这个想法不起作用?

好吧,但对吗?

当您指定nodeToDelete=nodeToDelete->next时;您的意思是,您的本地指针nodeToDelete现在引用了与nodeToDelete->next相同的内存位置。这两个指针之间没有其他关系。因此,当您指定nodeToDelete=nullptr;你实际上什么也没做:本地指针再也不用了,所以它指向的内存区域并不重要。

不幸的是,尽管您删除了该节点,但应该是最后一个节点仍然指向它以前的位置,因此您的下一个pop_back调用愉快地迭代到不可访问的内存中。

我想这是家庭作业,所以我可能不应该为你重写。但是,您可以通过实际修改应该是最后一个节点来修复它,而不仅仅是它下一个指针的本地副本。

当然,如果这是一个真正的项目,std::forward_list可能会有所帮助。:v

一切都应该很好,因为在此之前的节点(以前是倒数第二个节点(现在指向一个nullptr,标记列表的末尾。

好吧,但是吗?

当您分配nodeToDelete = nodeToDelete->next;时,您的本地指针nodeToDelete现在指向与nodeToDelete->next相同的内存位置。这两个指针之间没有其他关系。因此,当你分配nodeToDelete = nullptr;时,你实际上什么也没做:本地指针再也不用了,所以它指向的内存区域并不重要

不幸的是,应该是最后一个节点仍然指向它过去的位置,即使您对该节点进行了deleted,因此您的下一个pop_back调用愉快地迭代到不可访问的内存中。

我想这是家庭作业,所以我可能不应该为你重写。但是,您可以通过实际修改应该是最后一个节点来修复它,而不仅仅是它的next指针的本地副本。

当然,如果这是一个真正的项目,std::forward_list可能会有所帮助v