0

Given below is my code snippet for linked list. I am not able to add number. Whenever I try to add to my list, numbers are getting replaced, so my list never grows. Can you please let me know what is wrong in this code. It would also be very helpful if you could comment on my coding fashion.

   using namespace std;

struct node
{
  int number;
  std::shared_ptr<node> next;
};


bool isEmpty(std::shared_ptr<node> &head)
{
 return (head == NULL);
}


void add(std::shared_ptr<node> &head, int number)
{
 std:: shared_ptr<node> temp;
 temp.reset(new node);

 //temp = head; 

 cout<<"\n Adddress of head: "<<head.get();
// cout<<"\nAddress of temp: "<<temp.get();
 if(isEmpty(head))
 {
   head.reset(new node);
   head->number = number;
   head->next = NULL;
   cout<<"\nAdded first element";  
  }

  else
  {
     cout<<"\nAdding element to exisiting list";
     while(head->next!= NULL)
       { 
        cout<<"\n traversing to next element----->"<<temp->number;
    head = head->next;
       }     

     shared_ptr<node> newNode; 
     newNode.reset(new node);
     newNode->number = number;
     newNode->next = NULL;
     head->next = newNode;
     cout<<"\n address of newNode: "<<newNode.get();

   //  head->next = temp;      
  }   
  //cout<<"\nExiting add";
}



int main()
{
  int number;
  std::shared_ptr<node> head(nullptr);  
   char choice;
  add(head, number);

 return 0;
}
Username
  • 59
  • 2
  • 8
  • Regarding coding style/approach, try writing this without using any C++. After that version works perfectly, try the C++ version. – Joel Nelson Sep 16 '16 at 21:55
  • Code style: Use a stable indentation. The mark 1 eyeball spots patterns really well and you can use this to your advantage. – user4581301 Sep 16 '16 at 22:33
  • Recommend initializing `number` in `main`. Having a known value will make debugging easier on the brain. – user4581301 Sep 16 '16 at 22:36
  • Personally I think `shared_ptr` is the wrong choice here, think about what the destruction that can be wrought by unlinking a `node`, raw pointer would be better, but `std::shared_ptr temp; temp.reset(new node);` might as well be `std::shared_ptr temp(new node);` Bit less overhead. – user4581301 Sep 16 '16 at 22:40

2 Answers2

0

Why are you using reset on shared pointer?

http://en.cppreference.com/w/cpp/memory/shared_ptr/reset

Check the following example:

https://codereview.stackexchange.com/questions/33136/singly-linked-list-with-smart-pointers

Community
  • 1
  • 1
Techie
  • 21
  • 1
0

Let's take a walk through the add function. I've tweaked the indentation for easier reading.

void add(std::shared_ptr<node> &head, int number)
{
    std::shared_ptr<node> temp;
    temp.reset(new node);

What are you using temp for? Nothing that I can see.

    //temp = head;

    cout << "\n Adddress of head: " << head.get();
// cout<<"\nAddress of temp: "<<temp.get();
    if (isEmpty(head))
    {
        head.reset(new node);
        head->number = number;
        head->next = NULL;
        cout << "\nAdded first element";
    }

OK. That case looks good.

    else
    {
        cout << "\nAdding element to exisiting list";
        while (head->next != NULL)
        {
            cout << "\n traversing to next element----->" << temp->number;
            head = head->next;

Whups! Just moved the head. You just lost that first node element. No one points at it anymore. Shared pointer prevents the leak by destroying it for you. Nice, but you've still lost the data. Fortunately head points to the former head->next, preventing destruction when the former head goes to its grave with next. Shared pointer saves your bacon, but injects a load of extra overhead.

        }

        shared_ptr<node> newNode;
        newNode.reset(new node);
        newNode->number = number;
        newNode->next = NULL;
        head->next = newNode;
        cout << "\n address of newNode: " << newNode.get();

        //  head->next = temp;
    }
    //cout<<"\nExiting add";
}

On the coding style front, I would use a Linked List class to make this a bit easier to deal with:

#include <iostream>
class LinkedList // Ahhhr. Here be the class
{
    struct node // node is a private member of the class hidden away from sight.
    {
        int number;
        node * next;
    };
    node * head; // no shared pointer. We'll handle the memory ourselves.

public:
    LinkedList(): head(nullptr) // construct and init LinkedList
    {

    }

    // we need a copy constructor to be Rule of Three compliant
    LinkedList(const LinkedList & src): head(nullptr) // copy constructor
    {
        node * cur = src.head;
        while (cur != nullptr)
        {
            add(cur->number);
            cur = cur->next;
        }
    }
    ~LinkedList() // free up the nodes
    {
        while (head->next != nullptr)
        {
            node *temp = head;
            head = head->next;
            delete temp;
        }
        delete head;

    }

    // Need assignment operator to be Rule of Three compliant
    // OK this looks a bit weird. src is passed by reference which will 
    // trigger the copy constructor above to do the copy for us. Then we 
    // steal the head from the copy and null it so when src goes out of 
    // scope the destructor doesn't kill all the nodes we just took.
    // This is called the Copy-and-Swap idiom.
    LinkedList & operator=(LinkedList src)
    {
        head = src.head;
        src.head = nullptr;
        return *this;
    }

    bool isEmpty() // essentially unchanged. head is now a class member. 
                   // No need for parameter
    {
        return (head == NULL);
    }

    void add(int number)
    {
        // removed dead code

        if (isEmpty())
        {
            head = new node;
            head->number = number;
            head->next = NULL;
        }

        else
        {
            node * cur = head; // updates a temporary, not the head.
            while (cur->next != NULL)
            {
                cur = cur->next;
            }

            cur->next = new node;
            cur->next->number = number;
            cur->next->next = NULL;
        }
    }
};

// and a quick tester
int main()
{
    LinkedList list;
    list.add(1);
    list.add(2);
    list.add(3);

    return 0;
}

This allows the Linked List to easily be templated and saves trouble later.

More on the Rule of Three and Copy-and-Swap

Community
  • 1
  • 1
user4581301
  • 29,019
  • 5
  • 26
  • 45
  • Thank you for your answer. Could you please tell me what does LinkedList(): head(nullptr) mean? I thought pointers were initialized inside the constructor function. What does ":" mean when placed next to a constructor definition? – Username Sep 21 '16 at 21:28
  • @Username That is the [Member Initializer List](http://en.cppreference.com/w/cpp/language/initializer_list). Note on that link. The top third probably looks like insane gibberish to the uninitiated. Skip about 1/3 of the way down to **Explanation** and start reading there. TL:DR It's very powerful tool that allow you to initialize members before the body of the constructor is executed. This saves you from redundant constructions (members of a class are constructed before entering the body of the class's constructor) and allows you to inherit from base classes without a default constructor. – user4581301 Sep 21 '16 at 21:39