单链表 - 弹出函数
Singly Linked list - popback function
我正在尝试编写一个函数,该函数将最后一个元素从列表中弹出,但是我不断收到指向指针的非法de引用的错误。我在这里做错了什么?我的插入函数也出现分段错误,其代码位于底部。任何帮助,不胜感激。
这是我的弹出函数
template < typename T >
void List<T>::PopBack()
{
if (Empty())
{
std::cerr << "** List error: PopBack() called on empty listn";
return;
}
Link *oldLink = last_;
if (first_ == last_)
first_ = last_ = 0;
Link *currLink = GetPred(last_);
last_ = currLink;
last_->next_ = nullptr;
delete oldLink;
} // end PopBack()
这也是我正在调用的函数
template <typename T >
typename List<T>::Link* List<T>::GetPred ( Link* x )
{
Link* p = first_;
while ( p != nullptr && p->next_ != x )
p = p->next_;
return p;
}
这是我的插入功能
// Insert t at (in front of) i; return i at new element
template < typename T >
ListIterator<T> List<T>::Insert (ListIterator<T> i, const T& t)
{
if (Empty()) // always insert
{
i = End();
}
if (!i.Valid()) // null
{
std::cerr << " ** cannot insert at position -1n";
return End();
}
Link* newLink = NewLink(t);
Link* currLink = GetPred(i.curr_);
// leave i at new entry and return
newLink = currLink;
return i;
}
这是我的结束函数
// return iterator "1 past the back"
template < typename T >
ListIterator<T> List<T>::End()
{
Iterator i(last_->next_);
return i;
}
这是我的有效函数
// test cursor for legal dereference
template < typename T >
bool ConstListIterator<T>::Valid() const
{
return curr_ != nullptr;
}
这是我的空函数
template < typename T >
bool List<T>::Empty() const
{
return (first_ == nullptr);
}
检索方法
template < typename T >
T& ConstListIterator<T>::Retrieve() const
// Return reference to current t
// note conflicted signature - const method returns non-const reference
{
if (curr_ == nullptr)
{
std::cerr << "** Error: ConstListIterator<T>::Retrieve() invalid dereferencen";
exit (EXIT_FAILURE);
}
return curr_->Tval_;
}
如果你的列表有一个元素,我假设first_
和last
都指向该元素。那么,当 List 只包含一个元素时调用 PopBack 时会发生什么:
template < typename T >
void List<T>::PopBack()
{
if (Empty()) // Not empty so don't take the if
{
std::cerr << "** List error: PopBack() called on empty listn";
return;
}
Link *oldLink = last_;
// first_ and last_ are the same so set them to 0
if (first_ == last_)
first_ = last_ = 0; // Why 0 instead of nullptr ?
// GetPred(0) will return nullptr, i.e. currLink will be nullptr
Link *currLink = GetPred(last_);
// Last will be nullptr
last_ = currLink;
// Dereference of nullptr !!!!
last_->next_ = nullptr;
delete oldLink;
}
也许你可以做到:
template < typename T >
void List<T>::PopBack()
{
if (Empty()) {
std::cerr << "** List error: PopBack() called on empty listn";
return;
}
delete last_; // No reason for oldLink - just delete right away
// as you will not dereference last_ until it has
// a new value
if (first_ == last_)
{
first_ = last_ = nullptr;
}
else
{
Link *currLink = GetPred(last_);
last_ = currLink;
last_->next_ = nullptr;
}
}
方法 PopBack
在 first_ 等于 last_ 的情况下具有未定义的行为,因为起初两个节点都设置为 0
if (first_ == last_)
first_ = last_ = 0;
然后,您正在尝试访问 alreadt 等于 0 的节点的数据成员next
last_->next_ = nullptr;
函数可以写得更简单
template < typename T >
void List<T>::PopBack()
{
if ( Empty() )
{
std::cerr << "** List error: PopBack() called on empty listn";
return;
}
Link *oldLink = last_;
Link *currLink = GetPred( last_ );
last_ = currLink;
if ( last_ == nullptr )
{
first_ = last_;
}
else
{
last_->next_ = nullptr;
}
delete oldLink;
} // end PopBack()
据我所知,方法Insert
具有内存泄漏,因为首先分配了一个节点并将其地址分配给newLink
Link* newLink = NewLink(t);
然后重新分配此变量
newLink = currLink;
似乎该方法实际上什么也没插入。
它可以看起来像下面这样
// Insert t at (in front of) i; return i at new element
template < typename T >
ListIterator<T> List<T>::Insert (ListIterator<T> i, const T& t)
{
if (Empty()) // always insert
{
i = End();
}
if ( !i.Valid() ) // null
{
std::cerr << " ** cannot insert at position -1n";
return End();
}
Link* newLink = NewLink(t);
newLink->next = i.curr;
Link* currLink = GetPred( i.curr_ );
if ( currLink == nullptr )
{
first_ = newLink;
}
else
{
currLink->next = newLink;
}
i.curr = newLink;
return i;
}
相关文章:
- 链表,反向函数,数据结构
- 链表的泛型函数remove()与成员函数remove)
- 链表中的 C++ 析构函数
- 为什么我的双向链表删除函数会删除多个节点?
- 在 c++ 中具有向量的双向链表构造函数
- C++析构函数被意外调用双链表
- 修改链表主函数代码,用户将在其中输入节点的索引和数据以及正确的消息
- 双链表的擦除值函数,未知错误
- 使用函数引用指向节点的指针删除链表中的节点?
- 使用析构函数释放链表
- 为什么将函数的返回类型从结构节点*更改为void后,链表的元素没有显示create_ll和显示?
- 指针永远不会在链表深层复制构造函数中达到 null
- 程序在为链表创建推送函数时崩溃
- C++嵌套的迭代器类(在链表类中)Insert_After函数
- 合并 2 个排序的链表。必需的成员函数 bool Merge(List342 &list1):
- 双链表堆栈删除函数不起作用
- 这是在传递 int num 时创建搜索函数的正确方法吗?使用链表库
- 复制链表的构造函数
- 将链表传递给函数并确保它未被修改
- C++弹出函数链表