2015-03-19 5 views
0
template <class T> 
class Node 
{ 
public: 
T m_data;     // Data to be stored 
Node<T>* m_next;  // Pointer to the next element in the list 


// Purpose: Default constructor 
// Postconditions: next pointer set to NULL 
// ---INLINE--- 
Node() : m_next(NULL) {} 

// Purpose: Auxiliaty constructor, construct from parameters 
// Postconditions: data and next pointer set to parameters 
// ---INLINE--- 
Node(const T& x, Node<T>* p) 
     : m_data(x), m_next(p) {} 

}; 

template <class T> 
class LinkedList 
{ 

public: 

Node<T>* head;  // Pointer to the head of the list 

// Purpose: Default constructor 
// Postconditions: head pointer set to NULL 
// ---INLINE--- 
LinkedList() : head(NULL) {} 





template<class T> 
const LinkedList<T>& LinkedList<T>::operator =(const LinkedList<T>& rhs) 
{ 
    if(this != &rhs) 
    { 
     if(head != NULL) 
     { 
     clear(); 
     } 
     head = NULL; 
     Node<T>* rhsptr = rhs.head; 
     Node<T>* copyptr = new Node<T>; 
     copyptr->m_data = rhs->m_data; 
     while(rhs->m_next != NULL) 
     { 
     rhsptr = rhsptr->m_next; 
     copyptr = new Node<T>; 
     copyptr = copyptr->m_next; 
     copyptr->m_data = rhsptr->m_data; 
     } 
     copyptr->m_next = NULL; 

    } 
    return(*this); 

}Confused о Linked Список

COPY ОПЕРАТОРА

template<class T> 
LinkedList<T>::LinkedList(const LinkedList<T>& rhs) 
{ 

    *this = rhs; 
} 

Когда я компилирую, он говорит:

linkedlist.hpp:24:25: error: base operand of ‘->’ has non-pointer type ‘const

LinkedList’

copyptr->m_data = rhs->m_data; ^ linkedlist.hpp:25:13: error: base operand of ‘->’ has non-pointer type ‘const

LinkedList’

while(rhs->m_next != NULL)

Я смущен, потому что я объявил rhsptr как тип указателя поэтому я должен быть в состоянии использовать -> правильно?

Кроме того, я смущен, если это кодирование работает в целом. Мы учили в классе, что оператор копирования должен просто имитировать инициализацию и вызвать оператор =, но я видел, как некоторые коды делают наоборот. Их конструктор копирования закодирован, и оператор присваивания вызывает его.

EDIT 2: Этот блок кода дает ошибку сегмента, но я ничего не вижу. Любая помощь на этом фронте ценится.

+2

'rhsptr' действительно является указателем, но' rhs' является ссылкой, так что вы должны использовать оператор точки, как в 'РИТ. m_data'. Наверное, это то, что ты хотел написать? – roeland

ответ

0

Ваше объявление или rhs (что верно для конструктора копирования) объявляет его как ссылку, и, следовательно, вместо «->» вы должны использовать простой «.». где вы получаете ошибку.

Использование в «&» в параметрах функций семантический отличается от его использования в качестве оператора разыменования (с «адреса из-операций»), хотя и функциональна, они ведут себя во многом таким же образом, : Они не позволяют компилятору копировать объект при вызове функции. Ниже приведены примеры для каждого типа вызова:

/* This requires a copy of the node for use by the function 
    * The copy is placed on the top of the stack, and ceases to exist 
    * once the function exits. 
    * The copy is made via your copy constructor */ 
    void fooA(Node<int> N){} 


    /* This requires a copy of a pointer to your node. To access members, 
    * you use the -> operator */ 
    void fooB(Node<int> * N){} 

    /* This implicitly requires a copy of a pointer to your node, but this 
    * happens without you manually doing a dereference */ 
    void fooC(Node<int> &N){} 

    // Here we exemplify the call format 
    int main(void){ 
     Node<int> N; 
     fooA(N); 
     fooB(&N); 
     fooC(N); 
     return 0; 
    } 

(заметьте, я использовал только узел в качестве примера, это имеет место для всех типов в C++)

вызов путем ссылки (ваш "& rhs ") был создан, чтобы упростить sintax (используя«. »в вызываемой функции и не нуждаясь в« & »в вызывающей функции), чем семантика указателя (например:« * rhs »).

Что касается вашего второго вопроса, вы можете реализовать operator = как вызов конструктора копирования, наоборот, или наоборот, хотя, по моему опыту (и по личным предпочтениям), более типично писать код в виде копии конструктор, а затем ссылайтесь на это из своей реализации оператора.

EDIT: Я должен добавить, что в случае, если это было неясно, выполнение копии объекта часто оказывается более дорогим, чем использование указателя (или ссылки). Указатель обычно будет иметь порядок 4 или 8 байтов (32-битная 64-разрядная система), но даже простые объекты могут быть намного большими (например, Node должен быть 8 или 16 байтов, не считая затраченного времени на выполнение конструктора копирования).

0

Для вашего вопроса «Изменить 2». Эти строки кода:

copyptr = new Node<T>; 
    copyptr = copyptr->m_next; 

создаст новый узел с m_next значением NULL затем установите copyptr к этому значению. Это приводит к тому, что copyptr равен NULL, который затем вызывает ошибку при попытке его использования.

Вместо этого вы хотите обновить текущее значение copyptrm_next, чтобы указать на новый узел, а затем установить copyptr на этот новый узел.

Небольшое изменение в коде должны это сделать:

copyptr->m_next = new Node<T>; 
    copyptr = copyptr->m_next;