Francis Atienza
Francis Atienza

Reputation: 11

Confused about Linked List

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);

}

COPY OPERATOR

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

    *this = rhs;
}

When I compile, it says:

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)

I'm confused because I declared rhsptr as a pointer type so I should be able to use -> right?

Also, I am confused if this coding works in general. We've been taught in class that the copy operator should just imitate the initialization and call on the = operator but I've seen some codes doing the opposite. Their copy constructor is coded and the assignment operator calls on it.

EDIT 2: This block of code is giving a segment fault but I cannot see anything. Any help on that front is appreciated.

Upvotes: 0

Views: 221

Answers (2)

The Dark
The Dark

Reputation: 8514

For your "Edit 2" question. These lines of code:

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

will create a new Node with a m_next value of NULL then set copyptr to that value. This results in copyptr being NULL which will then cause a fault when you try to use it.

Instead you want to update the current copyptr's m_next value to point to the new node, then set copyptr to that new node.

A slight change to the code should do it:

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

Upvotes: 0

Andr&#233; Harder
Andr&#233; Harder

Reputation: 394

Your declaration or rhs (which is correct for a copy constructor) declares it as a reference, and thus, instead of the "->" you should use a simple "." where you're getting the error.

The use of an "&" in the parameters of a function is semantically distinct from its usage as a dereference operator (an "address-of-operation"), although functionally, they behave in much the same way: They prevent the compiler from making a copy of an object when calling a function. Below are examples for each call type:

    /* 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;
    }

(mind you, I only used Node as an example, this is the case for ALL types in c++)

The call by reference (your "&rhs") was actually created to allow for simpler sintax (using the "." in the called function, and not needing the "&" in the calling function) than the pointer semantics (e.g.: "*rhs").

As for your second question, you can implement operator= as a call to the copy constructor, visa-versa, or independently, though in my experience (and personal preference), it's more typical to write the code as the copy constructor, and then reference that from your operator implementation.

EDIT: I should add that, in case it wasn't clear, doing a copy of the object is often FAR more expensive than using a pointer (or reference) -- A pointer will typically be on the order of 4 or 8 bytes (32 vs 64 bit system), but even simple objects can be much larger (Node should be either 8 or 16 bytes, for example, not counting the time spent running the copy constructor).

Upvotes: 0

Related Questions