Reputation: 41
I am trying to implement a "facebook" like problem.
I have created a class called User
. A user has a list of friends.
I tried this using a C++ vector and it worked without any problems.
Then I tried changing the vector to a LinkedList
, using a template class I have.
The template has a copy constructor and destructor.
I have tested and debugged the template for other datatypes.
class User
{
private:
string uname;
//vector<User> myfriends;
LinkedList<User> myfriends;
public:
User() { uname = "none"; }
User(string n) { uname = n; }
string getName() { return uname; }
void addFriend(User &u)
{
//add u to me
myfriends.appendNode(u);
//add "me" to u
u.myfriends.appendNode(*this); //causes problem?
//myfriends.push_back(u); //when using vector
//u.myfriends.push_back(*this); //works when using vector
}
void listFriends()
{
cout << uname << " has " << myfriends.getSize() << " friends" << endl;
myfriends.displayList(); //prints values in linked list
}
friend ostream& operator<< (ostream& out, User u)
{
out << u.uname;
return out;
}
};
I want the addFriend function to make a "mutual" connection.
This works when I use a vector
, but when using this LinkedList
and this testing program:
User u1("joe");
User u2("sam");
u1.addFriend(u2);
u1.listFriends();
I get the correct output
joe has 1 friends
sam
However I also get a runtime error which tells me something funky is happening with my pointers.
"A problem caused the program to stop working correctly."
I am using Visual Studio Express 2017.
I am trying to figure out if there is some basic flaw with making the connections this way, trying to draw some pictures to work it out.
Any thoughts on what might be causing the runtime error?
Here's the displayList()
function:
template <class T>
void LinkedList<T>::displayList()
{
//"walk" the list and print each value
ListNode *nodePtr;
//to walk the list
//start at the beginning
nodePtr = head;
//while there is a node to print
while (nodePtr) {
//display the value
cout << nodePtr->data << endl;
//move to next node
nodePtr = nodePtr->next;
}
}
Here is displayList code in LinkedList template
template <class T>
void LinkedList<T>::displayList()
{
//"walk" the list and print each value
ListNode *nodePtr; //to walk the list
//start at the beginning
nodePtr = head;
//while there is a node to print
while (nodePtr)
{
//display the value
cout << nodePtr->data << endl;
//move to next node
nodePtr = nodePtr->next;
}
}
Here is appendNode
template <class T>
void LinkedList<T>::appendNode(T value)
{
ListNode *newNode; //to point to a new node
ListNode *nodePtr; //to move through the list
//allicate a new node and store value
newNode = new ListNode;
newNode->data = value;
newNode->next = nullptr;
//if list is empty make this the first node
if (!head)
head = newNode;
else // insert at end of list
{
//initialize nodePtr to head of list
nodePtr = head;
//"walk" the listt to find the last node
while (nodePtr->next) //if not null this is true
{
nodePtr = nodePtr->next;
}
//nodePtr now points to last node in list
//add the new node
nodePtr->next = newNode;
//remember it's next has already been assigned to null
}
numElements++;
}
Here is link https://repl.it/@prprice16/GrowlingFastRule
Upvotes: 2
Views: 128
Reputation: 179
You have
LinkedList<User> myfriends;
When you do
void addFriend(User &u)
{
//...
}
You will do a full copy of User, including the LinkedList object in it. However, inside your LinkedList, you did not specify an assignment operator, meaning your head for the User passed in will be directly assigned, leaving you with 2 LinkedList with the same head.
Hence the same head pointer will be freed twice.
Upvotes: 1