#c #class #operator-overloading #linked-list
#c #класс #оператор-перегрузка #связанный список
Вопрос:
Я сталкиваюсь с некоторыми ошибками сейчас, когда пытаюсь использовать созданный мной класс с двойной связью list. Моя реализация оператора = выглядит следующим образом:
template <typename T>
Dlist<T>amp; Dlist<T>::operator=(const Dlist amp;l)
{
copyAll(l);
return *this;
}
template <typename T>
void Dlist<T>::copyAll(const Dlist amp;l)
{
node *copyList = new node;
copyList = l.first;
while(copyList){
insertFront(copyList.first->o);
copyList = copyList->next;
}
delete copyList;
}
Обратите внимание, что o является указателем на данные в узле списка.
Мое намерение состоит в том, чтобы copyAll был настоящей глубокой копией. Разве это не так? Что-то не так с моими определениями методов класса здесь? Я новичок в связанных списках, поэтому очень ценю помощь!
РЕДАКТИРОВАТЬ: в частности, проблема, с которой я сталкиваюсь, заключается в том, что когда я создаю список и заполняю его, затем создаю новый список и устанавливаю его равным первому, всякий раз, когда я что-то делаю со вторым списком, это также изменяет первый список.
ПРАВКА2: Вот сам класс. Мне не разрешено добавлять какие-либо другие функции-члены:
template <typename T>
class Dlist {
public:
// Operational methods
bool isEmpty();
// EFFECTS: returns true if list is empty, false otherwise
void insertFront(T *o);
// MODIFIES this
// EFFECTS inserts o at the front of the list
void insertBack(T *o);
// MODIFIES this
// EFFECTS inserts o at the back of the list
T *removeFront();
// MODIFIES this
// EFFECTS removes and returns first object from non-empty list
// throws an instance of emptyList if empty
T *removeBack();
// MODIFIES this
// EFFECTS removes and returns last object from non-empty list
// throws an instance of emptyList if empty
// Maintenance methods
Dlist(); // ctor
Dlist(const Dlist amp;l); // copy ctor
Dlist amp;operator=(const Dlist amp;l); // assignment
~Dlist(); // dtor
private:
// A private type
struct node {
node *next;
node *prev;
T *o;
};
node *first; // The pointer to the 1st node (NULL if none)
node *last; // The pointer to the 2nd node (NULL if none)
void makeEmpty();
// EFFECT: called by constructors/operator= to establish empty
// list invariant
void removeAll();
// EFFECT: called by destructor/operator= to remove and destroy
// all list elements
void copyAll(const Dlist amp;l);
// EFFECT: called by copy constructor/operator= to copy elements
// from a source instance l to this instance
};
Комментарии:
1. Я не думаю, что этот код может компилироваться, вы используете
copyList
как указатель (-> next), так и ссылку (.first). Удаление в конце не имеет смысла,copyList
в этот момент всегда должно быть null.2. Он определенно компилируется, но не выполняет то, что должен.
Ответ №1:
По сути, разница между мелкой копией и глубокой копией заключается в том, копируете ли вы только сам указатель или копируете все данные, на которые указывает указатель. Не забудьте также вызвать базовый класс и скопировать все его члены, чтобы избежать частичной инициализации, если ваш объект является производным!
Как правило, вы хотите предоставить конструктор копирования для этой цели. Оператор присваивания похож на копирование, но присваивание фактически выполняется для уже созданного и, вероятно, уже инициализированного объекта.
Что касается того, правильно ли вы это делаете, это зависит от деталей реализации вашего класса, большинство из которых вы здесь не показали. То, что вы показали, выглядит неполным.
Возможно, вы захотите рассмотреть возможность использования std::list
до тех пор, пока вы не будете лучше знакомы с C и структурами данных, прежде чем пытаться реализовать свою собственную версию. В наши дни редко возникает реальная необходимость изобретать велосипед, кроме как ради любопытства или более полного изучения базовых концепций.
Комментарии:
1. Ну, это для моего класса, и они заставляют нас внедрять двусвязный список в образовательных целях XD. В противном случае я бы определенно использовал std::list!
Ответ №2:
Вы говорите «некоторые ошибки». Полезно упомянуть, что это такое, когда задаешь вопрос.
Тем не менее, посмотрите на первые две строки copyAll
. Первая строка выделяет новый узел, вторая перезаписывает этот указатель, теряя его навсегда. Возможно, вы имели в виду copyList.first = l.first
. Вам также потребуется создать новые узлы внутри цикла while.
Комментарии:
1. Добавил еще немного информации к моему сообщению. Я не могу выполнить copyList.first, как вы сможете сейчас сказать.
2. тогда вам нужно что-то вроде
this->first = copyList
, сразу после инструкции new . Просмотрите свой код на бумаге, строка за строкой, и посмотрите, какие указатели указывают куда. Также подумайте о том, куда ДОЛЖНЫ указывать указатели, и ваши ошибки и решения будут очевидны.