A few things jump out:
First, you could see what's going on and fix it a lot faster if you ran this bit of test code in your development environment's debugger. Debugger use is an essential skill to the productive programmer, so the sooner you learn it, the better.
Second is an ideological point, so ignore me if you disagree. The node
cannot have the information that the linked list can have about the status of the list, so the node should not link itself, unlink itself, or delete
linked node
s without being instructed to do so by the linked list. While self-managing behaviour is useful, it won't always be the correct behaviour for the list. I find it best to keep a node
really dumb.
Third, in a constructor, none of the variables are initialized until you initialize them. You can't count on them having a useful or predictable value, so
node(node &obj){
delete next;
enters into the realm of Undefined Behaviour. The value of next
has not been assigned so it's unknown and it's impossible to accurately predict what will happen if you attempt to delete
it.
Solution: Don't delete
it.
node(node &obj)
{
node* ptr = this;
node* optr = &obj;
while (true)
{
ptr->data = optr->data;
optr = optr->next;
if (optr == NULL)
break;
ptr->next = new node(1);
ptr = ptr->next;
}
}
There are a few improvement that can be made in there, but that's outside the scope of the question.
A side note:
void func(node a)
passes a
by value. This triggers the copy constructor possibly a bit earlier than you would expect. You may want to pass by reference here:
void func(node &a)
Finally,
node b(1);
b = a;
Does not trigger the copy constructor.
node b(1);
constructs b
with no additional links.
b = a;
uses the assignment operator, operator=
, to copy a
into b
.
But no operator=
has been defined. This violates the Rule of Three. What is The Rule of Three? Read the link and find out.
To you this means the next
pointer, and not the next
node
, is copied. You now have two node
s pointing to the linked node
, in other words the same list, and that's bad. Delete one and you delete the contents of the other, leaving the other invalid.
node & operator=(node other) // pass by value copies the node
{
delete next; // prevent leak of additional nodes. The smart destructor helps here.
data = other.data; // copy data
next = other.next; // steal remaining links from other. to save further copying
other.next = nullptr; // prevent destruction of the remaining links when
// other goes out of scope
return *this;
}
Rather than duplicate the work done copying in the copy constructor, we use the copy constructor by passing by reference.
As a useful side note,
node b = a;
will call the copy constructor for you and initialize b
with a
without constructing a "temporary" b
beforehand.
Any further problems I do not care about as they cannot be tested with the provided framework.