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

时间:2016-06-28 19:42:30

标签: c++ pointers dynamic-data

我们假设我只允许使用newdelete,并且在我的实施中没有智能指针。我没有使用哨兵节点。

以下是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."

在第一个结果后直接添加另一个pop_back会产生Aborted (core dumped)信号。

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

2 个答案:

答案 0 :(得分:2)

好的,但是吗?

当你指定nodeToDelete = nodeToDelete-&gt; next时;你说你的本地指针nodeToDelete现在指向内存中与nodeToDelete-&gt; next相同的位置。两个指针之间没有其他关系。所以当你然后分配nodeToDelete = nullptr;你实际上什么都不做:那个本地指针永远不会被再次使用,所以它所指向的内存区域并不特别重要。

不幸的是,即使你删除了那个节点,应该是最终节点仍然指向它曾经的位置,所以你的下一个pop_back调用会愉快地迭代到无法访问的内存。

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

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

答案 1 :(得分:1)

  

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

好的,但是吗?

当您指定nodeToDelete = nodeToDelete->next;时,您表示您的本地指针nodeToDelete现在引用内存中与nodeToDelete->next相同的位置。两个指针之间没有其他关系。因此,当您分配nodeToDelete = nullptr;时,您实际上什么都不做:本地指针永远不会再次使用,所以它指向的内存区域并不特别重要。

不幸的是,应该是最后一个节点仍然指向它以前的位置,即使你delete那个节点,所以你的下一个pop_back调用会愉快地迭代到无法访问的内存。

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

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