So, I've been on the process of making a linked list class, and right now I'm trying to make it so that two lists can be united through simple a + operator. Here is the current code, whole:
#include <iostream>
using namespace std;
// ---/ List Class /--- //
template <class Type>
struct Node {
Type core;
Node<Type> *next;
};
template <class Type>
class List {
public:
Node<Type> *start, *end;
unsigned int siz;
static const int END;
public:
// Genesis
List() {
start = NULL;
end = NULL;
siz = 0;
};
// ---
void push (const Type&, const int&);
// DEBUG
void show (void);
// +-*/
List operator+ (const List&);
List& operator= (const List&);
List& operator+= (const List&);
// Abbadon
~List() {
delete start;
delete end;
};
};
template <class Type>
const int List<Type>::END = -1;
// ---
template <class Type>
void List<Type>::push (const Type& elem, const int& pos = END) {
Node<Type> *aux;
aux = new Node<Type>;
aux->core = elem;
if (siz == 0) {
aux->next = NULL;
start = aux;
end = aux;
}
else {
if (pos == END) {
aux->next = NULL;
end->next = aux;
end = end->next;
}
else if (pos == 0) {
aux->next = start;
start = aux;
}
else {
Node<Type> *pesq = start;
for (int i = 1; (i < pos) && (pesq->next != NULL); i++) {
pesq = pesq->next;
}
aux->next = pesq->next;
pesq->next = aux;
}
}
siz++;
}
// DEBUG
template <class Type>
void List<Type>::show (void) {
Node<Type> *pesq = start;
while (pesq != NULL) {
cout << pesq->core << endl;
pesq = pesq->next;
}
cin.get();
}
// +-*/
template <class Type>
List<Type> List<Type>::operator+ (const List<Type>& nimda) {
List<Type> aux = *this;
aux.end->next = nimda.start;
aux.end = nimda.end;
aux.siz += nimda.siz;
return aux;
}
template <class Type>
List<Type>& List<Type>::operator= (const List<Type>& nimda) {
if (&nimda != this) {
start = nimda.start;
end = nimda.start;
siz = nimda.siz;
}
}
template <class Type>
List<Type>& List<Type>::operator+= (const List<Type>& nimda) {
*this = *this + nimda;
return *this;
}
// ---/ MAIN() /--- //
int main() {
List<int> adabo;
List<int> inakos;
adabo.push(1);
adabo.push(2);
inakos.push(3);
inakos.push(4);
adabo = adabo + inakos;
adabo.show();
}
Here are the overloaded operators:
template <class Type>
List<Type> List<Type>::operator+ (const List<Type>& nimda) {
List<Type> aux = *this;
aux.end->next = nimda.start;
aux.end = nimda.end;
aux.siz += nimda.siz;
return aux;
}
template <class Type>
List<Type>& List<Type>::operator= (const List<Type>& nimda) {
if (&nimda != this) {
start = nimda.start;
end = nimda.start;
siz = nimda.siz;
}
}
template <class Type>
List<Type>& List<Type>::operator+= (const List<Type>& nimda) {
*this = *this + nimda;
return *this;
}
And here is the main(), for testing:
// ---/ MAIN() /--- //
int main() {
List<int> adabo;
List<int> inakos;
List<int> foo;
adabo.push(1);
adabo.push(2);
inakos.push(3);
inakos.push(4);
foo = adabo + inakos;
foo.show();
}
Its output would supposedly be the values 1, 2, 3, and 4, and it indeed happens when I put the show function in the operator of + before aux returns:
template <class Type>
List<Type> List<Type>::operator+ (const List<Type>& nimda) {
List<Type> aux = *this;
aux.end->next = nimda.start;
aux.end = nimda.end;
aux.siz += nimda.siz;
aux.show() // Putting it here shows everything as expected
return aux;
}
It seems, however, that 'aux' is lost somewhere between its return of the function and the actual value received by 'foo' in main(), causing foo.show() to display random data endlessly.
What am I doing wrong?
Nevermind, found the problem!
What was happening was that operator= was making a 'duplicate', if one so can say, of the List to be passed over. The 'duplicate' List, when modified, would modify the original List as well, so in here...
template <class Type>
List<Type> List<Type>::operator+ (const List<Type>& nimda) {
List<Type> aux = *this; // ...aux, which would become a duplicate of the class...
aux.end->next = nimda.start;
aux.end = nimda.end;
aux.siz += nimda.siz;
return aux;
} // ...when destructed here, would destruct *this just as well, making all data be lost.
To solve this problem, instead of blandly passing over the pointers in the overloaded =...
template <class Type>
List<Type>& List<Type>::operator= (const List<Type>& nimda) {
if (&nimda != this) {
start = nimda.start;
end = nimda.start;
siz = nimda.siz;
}
}
...now it is made so that each element of the List is copied one by one:
template <class Type>
List<Type>& List<Type>::operator= (const List<Type>& nimda) {
if (&nimda != this) {
kill();
Node<Type> *aux = nimda.start;
while (aux != NULL) {
push(aux->core);
aux = aux->next;
}
}
}
This way, the receiving List gets a copy of all the elements of the original List without becoming itself.