Reputation: 11
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
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
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