список с двойным завершением

#c #linked-list

#c #связанный список

Вопрос:

Следующий код перестает работать, показывает пустой экран, показывает число, а затем выводит сообщение об ошибке, что код перестал работать.

 #include <iostream>
using namespace std;
class Link{
public:
  long ddata;
  Link *next;
  Link(long d){
    ddata=d;
  }
  void displaylin(){
    cout<<ddata<<"  "<<endl;
  }
};

class firstlast{
private :
  Link *first;
  Link * last;
public:
  firstlast(){
    first=NULL;
    last=NULL;
  }
  bool empthy(){
    return (first==NULL);
  }
  void insertfirst(long dd){
    Link *newlink=new Link(dd);
    if (empthy())
      last=newlink;
    newlink->next=first;
    first=newlink;
  }
  void insertlast(long dd){
    Link *newlink=new Link(dd);
    if ((empthy()))
      first=newlink;
    else
      last->next=newlink;
    newlink=last;
  }
  long deletefirst(){    //delete first link
    long temp=first->ddata;
    if (first->next==NULL)//only one item
      last=NULL;
    first=first->next;
    return temp;
  }
  void displayList(){
    cout<<"first -> last   "<<endl;
    Link *current=first;
    while(current!=NULL){
      current->displaylin();
      current=current->next;
    }
  }
};

int main(){
  firstlast *fl=new firstlast();
  fl->insertfirst(22);
  fl->insertfirst(44);
  fl->insertfirst(66);
  fl->insertlast(33);
  fl->insertlast(88);
  fl->insertlast(100);
  fl->deletefirst();
  fl->displayList();
  return 0;
}
  

Я думаю, что где-то есть переполнение, но я не могу найти, где. IDE показывает результат моей программы.

Комментарии:

1. Описание вашей проблемы действительно сложно понять. Не могли бы вы отредактировать свой вопрос, указав, какой именно результат вы получаете? Если код взрывается, вы использовали отладчик, чтобы попытаться точно определить, где он взрывается?

2. я добавил ссылку, где указан вывод

3. Недостаточно хорошо. Пожалуйста, убедитесь, что ваш вопрос заполнен без внешних ссылок, особенно тех, которые не являются интерактивными. Вы хотите предоставить максимум информации в своем вопросе, чтобы люди могли сразу понять, в чем ваша проблема. Если вы требуете, чтобы люди просматривали ссылки, чтобы помочь вам, вы теряете значительную часть аудитории здесь.

4. у меня проблема в том, что когда я запускаю этот код, представьте, как это происходит, появляется черное окно командной строки, показывает мне этот вывод 44 22 100 и перестает работать, показывая другую форму Windows, которая обычно появляется в случае некоторых ошибок

5. И пока вы добавляете его, отформатируйте код, чтобы он был читаемым.

Ответ №1:

Проблема в этой строке в insertlast(long) :

 newlink=last;
  

Это должно быть:

 last=newlink;
  

С этим изменением вывод становится:

первый -> последний 
44 
22 
33 
88 
100 

РЕДАКТИРОВАТЬ: как указал @Jared, ваш код страдает от утечек памяти. Это происходит всякий раз, когда вы выделяете память кучи с new помощью или malloc , но не освобождаете ее с помощью соответствующей функции «free».

Важно, чтобы каждый указатель, возвращаемый by new , освобождался ровно один раз by delete . Если вам не удается вызвать delete , то ваша программа пропускает память. Если вы вызываете delete более одного раза для «двойного освобождения» области, то ваша программа вызывает неопределенное поведение.

В этом коде:

   long deletefirst(){    //delete first link
    long temp=first->ddata;
    if (first->next==NULL)//only one item
      last=NULL;
    first=first->next;
    return temp;
  }
  

обратите внимание, что это first=first->next; приводит к потере указателя на часть динамически выделяемой памяти. Помните, что для этого first был установлен результат new , поэтому вам необходимо delete first перед перезаписью first указать указатель на другую область динамически выделяемой памяти.

Кроме того, вам нужно добавить в свой класс:

  1. Деструктор для освобождения всей памяти, которая не была освобождена с помощью вызовов deletefirst() .
  2. Конструктор копирования для создания глубокой копии firstlast экземпляров.
  3. Перегрузка оператора присваивания, operator=(const firstlastamp; fl) , который также создает глубокую копию.

Ответ №2:

Во-первых, ваш метод insertLast приводит к утечке памяти, поскольку вы фактически никогда не подключаете следующие указатели вновь созданных ссылок к чему-либо. Вы просто переназначаете локальный указатель newlink, который сразу же выходит из области видимости. Последующие вызовы insertLast оставляют память в пространстве. Это также может быть причиной вывода ошибки.

Во-вторых, ваш метод deleteFirst на самом деле ничего не удаляет, но оставляет ссылку, выделенную с помощью new out в памяти, на которую больше ничего не указывает. Еще одна утечка памяти.

Комментарии:

1. как я могу этого избежать? я имею в виду второй случай

2. Один из способов сделать это — создать временную ссылку * и инициализировать ее сначала. Затем, как только вы сначала перейдете к следующему узлу, явно вызовите delete для той временной ссылки *, которую вы создали. Дело в том, что вам нужно фактически вызвать delete для этого объекта Link, поскольку вы создали его с помощью ключевого слова new .