main
int main() {
LinkList<int>* a = new LinkList<int>();
for (int i = 1; i < 100; ++i)
{
a->Add(i);
}
for (int i = 0; i < a->Size(); ++i) {
cout << a->Get(i) << endl;
}
delete a; //在这显示:已引发异常
a = nullptr;
}
Link
template <class T>
struct Link {
T data;
struct Link* next;
struct Link* last;
};
LinkList
template <class T>
LinkList<T>::LinkList() {
head = new Link<T>();
head->next = head;
head->last = head;
count = 0;
}
template <class T>
LinkList<T>::~LinkList() {
while (head != nullptr) {
Link<T>* link = head->next;
delete head;
head = link;
}
}
template <class T>
bool LinkList<T>::IsEmpty() const {
return count == 0;
}
template <class T>
int LinkList<T>::Size() const {
return count;
}
template <class T>
T& LinkList<T>::Get(const int index) const {
Link<T>* link = head;
for (int i =0; i<=index; ++i)
{
link = link->next;
}
return link->data;
}
template <class T>
int LinkList<T>::IndexOf(const T& element) const {
Link<T>* link = head;
for (int i =0; i < count ; ++i)
{
link = link->next;
if ( link->data == element )
{
return i;
}
}
link = nullptr;
return -1;
}
template <class T>
void LinkList<T>::Erase(const int index) {
Link<T>* link = head;
for (int i =0; i < index; ++i)
{
link = link->next;
}
link->next->last = link->last;
link->last->next = link->next;
count--;
link = nullptr;
}
template <class T>
void LinkList<T>::Add(const T& elememt) {
Link<T>* link = new Link<T>();
link->data = elememt;
link->next = head;
link->last = head->last;
head->last->next = link;
head->last = link;
link = nullptr;
count++;
}
template <class T>
void LinkList<T>::Insert(const int index, const T& element) {
Link<T>* link = head;
for (int i =0; i < index; ++i)
{
link = link->next;
}
Link<T>* tmp = new Link<T>();
tmp->data = element;
tmp->next = link;
tmp->last = link->last;
link->last->next = tmp;
link->last = tmp;
count++;
}
“去掉 delete a;就可以执行” 这种思路不是正解哈,相当于你不销毁内存,而是靠进程释放销毁内存。
你的问题不在于调用了delete a,而是在于LinkList的析构函数~LinkList写的有问题。
因为你这写的是个循环双向链表,而在析构函数种你采用delete掉head所指节点以释放内存,所以在head指向最后一个节点时,最后一个节点的next指向你第一个删除的节点地址,这块内存释放了,其值为任意随机值,但是你的判断条件为 head != nullptr,就是这里错了。
因为 nullptr 的值为 0,但head此时是一个任意值,不等于0满足,所以会走到循环中,对无效内存再进行一次delete。不信你可以printf("%x", nullptr); 看看是多少。
所以判断指针为空我们一般用另一个写法。 !head。
template <class T>
LinkList<T>::~LinkList() {
//while (head != nullptr) { 这句错了哈
while (!head) {
Link<T>* link = head->next;
delete head;
head = link;
}
}
你这个链表不是单向列表,所有的节点都有next,所以
LinkList<T>::~LinkList() {
while (head != nullptr) {
Link<T>* link = head->next;
delete head;
head = link;
}
这个析构函数是错误的。你会循环删除节点,当所有节点删除后,你又会转到之初的head进行delete,但此时这个head已经给释放掉了,指针就成了野指针,释放自然会崩溃了。你最好记住这个head,当再次循环到这个head指针时,结束释放。比如
LinkList<T>::~LinkList() {
Link<T> *p = head;
while (head != nullptr) {
Link<T>* link = head->next;
if(link == p)
break;
delete head;
head = link;
}
去掉 delete a;就可以执行
main函数改一下试试:
int main() {
LinkList<int> a;// = new LinkList<int>();
for (int i = 1; i < 100; ++i)
{
a.Add(i);
}
for (int i = 0; i < a.Size(); ++i) {
cout << a.Get(i) << endl;
}
//delete a; //在这显示:已引发异常
//a = nullptr;
}
您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!