2

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

14
  • 1
    If you want us to help with bugs in your LinkedList you need to post a minimal example. Commented Apr 25, 2018 at 23:59
  • 1
    Also you'll get much better help if you post a repl.it link Commented Apr 26, 2018 at 0:01
  • The linked list works in other programs, but I could post it. My question is about the reciprocal nature of the lists in two objects pointing to each other, whether there is a fundamental issue there that I need to consider. Commented Apr 26, 2018 at 0:19
  • show your displayList Commented Apr 26, 2018 at 0:22
  • repl.it/@prprice16/GrowlingFastRule Commented Apr 26, 2018 at 0:29

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

14 Comments

Aaahhh!!! So I need to overload operator= to do a deep copy of the list? I think I get it...!
It is better for you to simply use a LinkedList<User*> instead.
wait or do I need to overload operator== in User? to make sure it actually makes a copy? But I want to modify the user object that is passed in (to make the friendship mutual).
When you say simply use a LinkedList<User> ... but I need the list inside User, that is what I have.
Or do I need a copy constructor for User?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.