C++ 单链表-弹出功能
我试图编写一个函数,弹出列表中的最后一个元素,但我不断收到一个错误,指向非法的指针反引用。我做错了什么?我的插入函数也有分段错误,代码在底部。感谢您的帮助 这是我的弹出式功能C++ 单链表-弹出功能,c++,linked-list,singly-linked-list,C++,Linked List,Singly Linked List,我试图编写一个函数,弹出列表中的最后一个元素,但我不断收到一个错误,指向非法的指针反引用。我做错了什么?我的插入函数也有分段错误,代码在底部。感谢您的帮助 这是我的弹出式功能 template < typename T > void List<T>::PopBack() { if (Empty()) { std::cerr << "** List error: PopBack() called on empty list\n"; ret
template < typename T >
void List<T>::PopBack()
{
if (Empty())
{
std::cerr << "** List error: PopBack() called on empty list\n";
return;
}
Link *oldLink = last_;
if (first_ == last_)
first_ = last_ = 0;
Link *currLink = GetPred(last_);
last_ = currLink;
last_->next_ = nullptr;
delete oldLink;
} // end PopBack()
模板
void List::PopBack()
{
if(空())
{
标准::cerr next_uu=nullptr;
删除旧链接;
}//结束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;
}
模板
类型名称列表::链接*列表::GetPred(链接*x)
{
Link*p=第一个;
while(p!=nullptr&&p->next\ux)
p=p->next;
返回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 -1\n";
return End();
}
Link* newLink = NewLink(t);
Link* currLink = GetPred(i.curr_);
// leave i at new entry and return
newLink = currLink;
return i;
}
//在i前面插入t;在新元素处返回i
模板
ListIterator列表::插入(ListIterator i,常量T&T)
{
if(Empty())//始终插入
{
i=结束();
}
如果(!i.Valid())//null
{
标准:cerr
ListIterator列表::End()
{
迭代器i(上一个->下一个);
返回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;
}
//合法解除引用的测试游标
模板
bool ConstListIterator::Valid()const
{
返回电流=空PTR;
}
这是我的空函数
template < typename T >
bool List<T>::Empty() const
{
return (first_ == nullptr);
}
模板
bool List::Empty()常量
{
返回值(第一个=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 dereference\n";
exit (EXIT_FAILURE);
}
return curr_->Tval_;
}
模板
T&ConstListIterator::Retrieve()常量
//返回对当前t的引用
//注意冲突签名-const方法返回非const引用
{
if(curr_==nullptr)
{
标准::cerr Tval_;
}
如果您的列表有一个元素,我假设first
和last
都指向该元素。那么当列表只包含一个元素时调用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 list\n";
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;
}
模板
void List::PopBack()
{
if(Empty())//不是空的,所以不要使用if
{
标准::cerr next_uu=nullptr;
删除旧链接;
}
也许你可以:
template < typename T >
void List<T>::PopBack()
{
if (Empty()) {
std::cerr << "** List error: PopBack() called on empty list\n";
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;
}
}
模板
void List::PopBack()
{
if(空()){
标准::cerr next_uu=nullptr;
}
}
当first_uu等于last_u时,方法弹出式
具有未定义的行为,因为最初两个节点都设置为0
if (first_ == last_)
first_ = last_ = 0;
然后您尝试访问ALREAD等于0的节点的数据成员next
last_->next_ = nullptr;
该函数可以编写得更简单
template < typename T >
void List<T>::PopBack()
{
if ( Empty() )
{
std::cerr << "** List error: PopBack() called on empty list\n";
return;
}
Link *oldLink = last_;
Link *currLink = GetPred( last_ );
last_ = currLink;
if ( last_ == nullptr )
{
first_ = last_;
}
else
{
last_->next_ = nullptr;
}
delete oldLink;
} // end PopBack()
然后重新分配这个变量
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 -1\n";
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;
}
//在i前面插入t;在新元素处返回i
模板
ListIterator列表::插入(ListIterator i,常量T&T)
{
if(Empty())//始终插入
{
i=结束();
}
如果(!i.Valid())//null
{
标准:cerr next=i.curr;
Link*currLink=GetPred(i.curr);
如果(currLink==nullptr)
{
第一个=新链接;
}
其他的
{
currLink->next=newLink;
}
i、 curr=newLink;
返回i;
}
请发布准确的错误消息同时发布End()、Valid()、Empty()函数。@jpo38**error:ConstListIterator::Retrieve()无效的取消引用,这是我在尝试从列表中弹出反向链接时遇到的错误。我在编译时没有收到任何错误。那么为什么不发布Retrieve()
code then?@maxpain121:请发布一个MCVE:我可以问一下为什么GetPred返回一个nullptr吗?我是不是从一开始就给它一个nullptr?我对链表还是很陌生,唯一需要做的是一个双链表实现,它更容易实现,因为我可以使用prev指针。您刚刚完成了first\u=last\u0;
在调用GetPred之前的PopBack中。因此GetPred将返回NullPtrTank you,我将尝试这些,看看是否有效!我肯定在其他地方有错误,因为每次在测试工具中调用PopBack时,我都会得到**错误:ConstListIterator::Retrieve()无效的取消引用,然后程序终止。我在没有任何元素、1个元素、2个元素等的情况下尝试了此操作,每次都会出现这种情况。@maxpain121我指出了您显示的函数中的错误。对于我没有看到的代码,我不能说什么。
// 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 -1\n";
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;
}