Дважды связанные списки в C++

у меня есть задание, которое требует от нас, чтобы реализовать двусвязный список класса. По какой-то причине они определили узел struct следующим образом:

struct node {
  node   *next;
  node   *prev;
  T      *o;
};

мне кажется, что было бы намного проще написать класс, если бы член структуры "данные" не был указателем. Излишне говорить, что я не могу изменить его, поэтому мне придется просто обойти его. Я попытался реализовать метод, который добавляет элемент в начало списка выглядит следующим образом:

template <typename T>
void Dlist<T>::insertFront(T *o) {
    node *np = new node;
    T val = *o;

    np->o = &val;
    np->prev = NULL;
    np->next = first;

    if (!isEmpty()) {
        first->prev = np;
    } else {
        last = np;
    }
    first = np;
}

пока используя ddd для отладки, я понял, что все работает нормально в первый раз, когда вы вставляете номер, но во второй раз все запутывается, так как, как только вы установите "val" на новый элемент, он "перезаписывает" первый, так как использовался адрес памяти val. Я пробовал делать другие вещи, например, вместо того, чтобы просто иметь переменную "val", делая следующее:

T *valp = new T;
T val;
valp = &val;
val = *o;

np->o = valp

Это, похоже, тоже не сработало. Я думаю, это потому, что это просто более сложная форма то, что я сделал выше, просто с дополнительной утечкой памяти:)

любые идеи/указатели в правильном направлении было бы здорово.

5 ответов


на T val вы создаете автоматическую переменную. Ваша ошибка-сохранение адреса этой переменной стека.

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

ваша ошибка в вашей последней попытке здесь:

valp = &val;

изменения valp до укажите куда-нибудь еще (адрес val), когда вы вероятно пытаюсь копировать данные Вэл, а не его адрес.

данные, передаваемые функции должны быть скопированы в новую память, где valp очков.


Я не думаю, что вы должны делать это:

T val = *o;

С o элемента в структуре узла является указателем, а параметр insertFront также является указателем, ваш инструктор, вероятно, намеревается, чтобы вы взяли указатель, который вам дали, и сохранили его в списке, а не сделали копию объекта и сохранили указатель на это. Просто храните o указатель, переданный в insertFront как o член узлом и вы должны быть в порядке.


 T val = *o;

    np->o = &val;

эта часть подозрительна. Подсказка заключается в том, что память, выделенная в стеке в функции, не будет доступна, как только функция выйдет за рамки.


ваш код не соответствует вашему определению node -- in node вы определяете data member, но в вашем коде вы используете .

в любом случае вам придется сделать два динамических распределения, чтобы добавить каждый узел-один для самого узла и один для объекта данных, на который он будет указывать. Когда вы выделяете этот объект данных, вы также можете назначить возвращаемое значение из new непосредственно к указателю в вашем узле. Тогда вам нужно будет скопировать объект данных, указатель которого был передан в только что выделенный объект данных, на который указывает указатель в узле.


вы думаю полезная нагрузка указателя неудобна. Но, возможно, список предназначен для создания ссылки на существующие объекты, как в:

struct A { int i; };
A as[10] = { 1,2,3,4,5,6,7,8,9,10 };

LinkedList primes_in_my_data;
insertFront( primes_in_my_data, &as[1] );
insertFront( primes_in_my_data, &as[2] );
insertFront( primes_in_my_data, &as[3] );
insertFront( primes_in_my_data, &as[5] );
insertFront( primes_in_my_data, &as[7] );

// now I have a linked list of primes, and caused no extra memory allocation
// (except for the list overhead)