I’m writing some C++ code for a simple “Node” class. This is basically a class used to manage a linear linked list. I normally perform this with a struct but I’m trying get a better handle of OOP and classes. What I’ve got thus far for the Node class is (note: the String class is my version (trimmed down) of a typical “string” class, it implements a copy constructor, assignment overload, destructor, etc. In testing it has worked great and seems completely self contained):
class Node {
public:
//Constructor
//-----------
Node() : next_(0) {} //inline (String constructor called)
//Destructor
//----------
~Node();
//Copy Constructor
//----------------
Node(const Node &);
//Operator Overload: =
//---------------------
//In conjunction with copy constructor. Protects Class.
Node & operator=(const Node &);
private:
String relatedEntry_;
Node * next_;
};
Creating one instance works fine (ie. Node node;) but when I create an instance that calls the Copy Constructor I end up with segfaults at the very end of my program, as it’s cleaning up. The difference between using a struct for a linked list vs a class plays tricks with me a little and I think I’m missing something key here. Here is the implementation for the Default Constructor, Copy Constructor, and Overloaded Assignment Operator:
//Constructor inlined
//Destructor
Node::~Node()
{
Node * curr = next_;
while (curr) //cycle through LL and delete nodes
{
Node * temp = curr; //hold onto current
curr = curr->next_; //increment one
delete temp; //delete former current
}
}
//Copy Constructor
Node::Node(const Node & cp)
{
std::cout << "in CopyCon" << std::endl;
relatedEntry_ = cp.relatedEntry_; //calls String class copy constructor/assignment overload
Node * curr = cp.next_; //for clarity, for traversal
while (curr) //copies related entry structure
{
Node * oldNext = next_;
next_ = new Node;
next_->next_ = oldNext; //'next' field (assign prior)
next_->relatedEntry_ = curr->relatedEntry_; //String class copy
curr = curr->next_; //increment
}
}
//OO: =
Node & Node::operator=(const Node & cp)
{
std::cout << "in OO: =" << std::endl;
if (this == &cp)
return *this; //self assignment
delete next_; //delete LL
relatedEntry_ = cp.relatedEntry_; //String Class Assignment Overload
Node * curr = cp.next_; //for clarity, for traversal
while (curr)
{
Node * oldNext = next_; //hold onto old
next_ = new Node;
next_->next_ = oldNext; //set next to old
next_->relatedEntry_ = curr->relatedEntry_; //set this string to cp string
curr = curr->next_; //increment
}
return *this;
}
Note that using the Overloaded Assignment Function seems to work fine (no segfaults) even though it’s virtually the same code… I’m assuming it has to do with the fact that both objects are already initialized before the assignment takes place?
//This seems to work ok
Node node1;
Node node2;
node2 = node1;
I’ve been at this bug for a couple of hours and I have got to get some rest. I’d really appreciate any insight into this. Thanks.
In the copy constructor loop, you have this line:
However, in the first round in the loop the value of
next_can by, well, anything and most likely notNULL. This means that the last node will a have a non-null pointer.Initialize it to
NULLbefore the loop and it should work.