Пытаясь написать собственную имплементацию связанного списка в C ++, код segfaults после нажатия 3 элементов в списке - PullRequest
0 голосов
/ 29 декабря 2018

Я пытался написать свою собственную реализацию связанного списка, но код не работает, когда я пытаюсь получить доступ к третьему элементу или чему-либо после него.Добавление элементов не вызывает сегрегацию, а доступ делает.Я не могу найти ошибку указателя в моей функции get ().

Каждый узел в списке хранит данные (из шаблона t) и указатель, ведущий к следующему узлу.У меня есть две функции для всего: одна для первого элемента и одна для любых последующих элементов.Функция get () для последующих элементов всегда segfaults.У меня есть некоторые отладочные сообщения в функции, которые выдают результаты, которые я не могу объяснить.Например, если я выполняю запрос get () для второго элемента, а затем для третьего, код не переходит в segfault, но он возвращает явно неверные результаты.Размещенные мной отладочные сообщения указывают, что segfault происходит, когда второй элемент вызывает функцию, чтобы проверить третий элемент, если он вообще возникает.Попробуйте код с и без строки cout << newList.get (2) << endl;и вы получите очень разные результаты.</p>

Одной из возможных причин является хранение указателя. У меня есть функция get (), которая выводит указатель каждого элемента (кроме первого) по мере его циклического перемещения, и сравнивает их с указателями, выведенными функцией add ()., и и указатели и для элементов 0 и 1 совпадают, но 2 и последующие не совпадают, и я не могу понять, почему это так.

#include <iostream>
using namespace std;



template <class T> class myLinkedList{
T data;
myLinkedList<T> *next = NULL;

public:
    myLinkedList(T input){
        data = input;

    }
    void add(T input){
        if(next == NULL){
            myLinkedList<T> newItem(input);
            next = &newItem;
            cout << "adding to list, data is " << input << ", pointer is " << next << endl;
        }else{
            myLinkedList<T> nextEntry = *next;
            nextEntry.add(input);
        }
    }


    T getData(){
        return data;
    }
    //the start  of the get function, only used by the first entry in the list
    T get(int entry){
        int currentPosition = 0;
        if(entry == currentPosition){
            return getData();
        }else{
            //defrefrence the pointer anc check the next entry
            myLinkedList<T> nextEntry = *next;
           return nextEntry.get(entry, ++currentPosition);
        }
    }

private:
    //this vesion is the hidden, private vesion only used by nodes other than the first one
    //used to keep track of position in the list
    T get(int entry, int currentPosition){
        //cout << currentPosition << endl;
        if(entry == currentPosition){
            return data;
        }else{
            //derefrence the pointer and check the next entry
            cout << next << endl;
            myLinkedList<T> nextEntry = *next;
            currentPosition++;
           T output = nextEntry.get(entry, currentPosition);
           return output;
        }

    }


};
int main(){
myLinkedList<int> newList(3);
newList.add(4);
newList.add(5);
newList.add(7);
newList.add(9);
cout << newList.get(2) << endl;
cout << newList.get(3) << endl;
return 0;
}

Результаты явно ошибочны - программа должна выплевыватьдва набора указателей, а также числа 5 и 7 (элементы списка)

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

У меня был прорыв!Следующее решение Сержа было полезным, но нужно было сделать еще одно изменение - вместо создания ссылки на функцию в блоке else моей функции добавления, например,

 myLinkedList<T> nextEntry = *next;
 nextEntry.add(input)

Мне нужно было использовать указатель напрямую, как в

next->add(input)

Я не знал мой синтаксис указателя / объекта

0 голосов
/ 29 декабря 2018

Одна из ваших главных проблем здесь:

if(next == NULL){
    myLinkedList<T> newItem(input); // <<<<<<<<<<<<<
    next = &newItem;
    cout << "adding to list, data is " << input << ", pointer is " << next << endl;
}

Вы размещаете элемент в стеке внутри области действия if.Затем вы делаете рядом, чтобы указать на этот пункт.Но ... время жизни предмета ограничено этой областью.Как сын, когда вы выходите из области видимости, этот предмет больше не существует.Вы должны выделить его динамически с помощью «новых» или других методов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...