Linked list implemented as classes, not imperative code As an update to previous code I've submitted:

Improvements this time are mainly having everything moved to a class, before I plough on and add more functionality (I've come back to C++ after a few years away and this is a revision exercise).

#include &lt;iostream&gt;
#include "LinkedList.h"

class LinkedList
{
public:
    LinkedList(void);
    ~LinkedList(void);
    void traverseList();
    int length();
    void push(int data);

private:
    struct node{
    int data;
    node *pointee;
    };

    node *head;
    node *last;
    int count;
};

LinkedList::LinkedList(void)
{
        head = new node();
    last = new node();
    head-&gt;data = 0;
    head-&gt;pointee = last;
    last-&gt;data = 0;
    last-&gt;data = NULL;
    count = 2;
}

LinkedList::~LinkedList(void)
{
}

/*
    To be replaced with an iterator and an overloaded print operator for output
*/
void LinkedList::traverseList(){
    for(node *iterator = LinkedList::head ; iterator ; iterator = iterator-&gt;pointee)
    {
        std::cout &lt;&lt; iterator-&gt;data &lt;&lt; std::endl;
    }
}

int LinkedList::length(){
    return LinkedList::count;
}

void LinkedList::push(int data){

    node *newNode = new node();
    newNode-&gt;data = data;
    newNode-&gt;pointee = NULL;
    last = newNode;
    ++count;
}

int main(){

    LinkedList list;

    for(int i=1 ; i&lt;4 ; i++)
    {
        list.push(i);
    }

    int length = list.length();
    std::cout &lt;&lt; length &lt;&lt; std::endl;
    list.traverseList();
    return 0;
}
Since we have no clean implementations:

The thing to notice is that the push_back() and erase() become trivial if you use a sentinal. This is because you do not need to test for NULL in any part of the code.

    Node(Node* after)
    {
        prev          = after;
        next          = after-&gt;next;
        prev-&gt;next    = this;
        next-&gt;prev    = this;
    }
    ~Node()
    {
        prev-&gt;next  = next;
        next-&gt;prev  = prev;
    }

    iterator push_back(T const&amp; value)
    {
        tail    = new ValueNode(value, tail);

        // If new succeeded then increment count
        ++count;
        return iterator(tail);
    }

    void erase(iterator const&amp; i)
    {
        // Get the value we will set as tail if the delete works
        Node*   newTail = (tail == i.node)
                            ? i.node-&gt;prev
                            : tail;
        delete i.node;
        // Delete worked now we can update the state.
        tail    = newTail;
        --count;
    }


Here is the whole code

#ifndef THORS_ANVIL_UTILITY_LINKED_LIST
#define THORS_ANVIL_UTILITY_LINKED_LIST

#include &lt;algorithm&gt;
#include &lt;functional&gt;

template&lt;typename T&gt;
class LinkedList
{
    struct Node
    {
        Node*   prev;
        Node*   next;
        Node(Node* after)
        {
            prev          = after;
            next          = after-&gt;next;
            prev-&gt;next    = this;
            next-&gt;prev    = this;
        }
        ~Node()
        {
            prev-&gt;next  = next;
            next-&gt;prev  = prev;
        }
        void swap(Node&amp; rhs) throw()  { std::swap(prev, rhs.prev); std::swap(next, rhs.next);}
    };
    struct ValueNode: Node
    {
        ValueNode(T const&amp; value, Node* after)
            : Node(after)
            , data(value)
        {}
        T       data;
    };

    Node    head;
    Node*   tail;
    int     count;

    public:
        struct Iterator: std::iterator&lt;std::input_iterator_tag, T, ptrdiff_t, const T*, const T&amp;&gt;
        {
            Iterator(Node* node): node(node){}

            T&amp;       operator*()        {return  static_cast&lt;ValueNode*&gt;(node)-&gt;data;}
            T*       operator-&gt;()       {return &amp;static_cast&lt;ValueNode*&gt;(node)-&gt;data;}
            T const&amp; operator*()  const {return  static_cast&lt;ValueNode*&gt;(node)-&gt;data;}
            T const* operator-&gt;() const {return &amp;static_cast&lt;ValueNode*&gt;(node)-&gt;data;}

            Iterator&amp; operator++()     /*prefix*/  { node = node-&gt;next; return *this;}
            Iterator&amp; operator--()     /*prefix*/  { node = node-&gt;prev; return *this;}
            Iterator  operator++(int)  /*postfix*/ { Iterator result(*this);this-&gt;operator++(); return result;}
            Iterator  operator--(int)  /*postfix*/ { Iterator result(*this);this-&gt;operator--(); return result;}

            bool operator !=(Iterator const&amp; rhs) const    { return node != rhs.node;}
            bool operator ==(Iterator const&amp; rhs) const    { return !(*this != node);}

            mutable Node*   node;
        };

        LinkedList()
            : tail(&amp;head)
            , count(0)
        {}

        ~LinkedList()
        {
            clear();
        }

        void clear()
        {
            while(head.next != &amp;head)
            {
                Node*   old = head.next;
                head.next   = head.next-&gt;next;
                --count;
                delete old;
            }
        }

        LinkedList(LinkedList const&amp; copy)
            : tail(&amp;head)
            , count(0)
        {
            std::for_each(copy.head-&gt;next, copy.head, std::bind1st(std::mem_fun(&amp;LinkedList::push_back), this));
        }
        LinkedList&amp; operator=(LinkedList rhs)
        {
            rhs.swap(*this);
            return *this;
        }
        void swap(LinkedList&amp; rhs) throw()
        {
            std::swap(head,     rhs.head);
            std::swap(tail,     rhs.tail);
            std::swap(count,    rhs.count);
        }

        bool    isEmpty()   const { return &amp;head == tail; }
        size_t  size()      const { return count; }

        typedef Iterator           iterator;
        typedef Iterator const     const_iterator;

        iterator push_back(T const&amp; value)
        {
            tail    = new ValueNode(value, tail);
            ++count;
            return iterator(tail);
        }

        void erase(iterator const&amp; i)
        {
            Node*   newTail = (tail == i.node)
                                ? i.node-&gt;prev
                                : tail;
            tail    = newTail;
            --count;
            delete i.node;
        }

        iterator begin()                {return iterator(head.next);}
        const_iterator begin() const    {return iterator(head.next);}
        iterator end()                  {return iterator(&amp;head);}
        const_iterator end() const      {return iterator(&amp;head);}
};
#endif


Then Main

#include &lt;LinkedList.h&gt;
#include &lt;iostream&gt;

int main()
{
    LinkedList&lt;int&gt; list;
    list.push_back(5);
    LinkedList&lt;int&gt;::iterator item = list.push_back(7);
    for(LinkedList&lt;int&gt;::iterator loop = list.begin(); loop != list.end(); ++loop)
    {
        std::cout &lt;&lt; *loop &lt;&lt; "\n";
    }
    list.erase(item);
    for(LinkedList&lt;int&gt;::iterator loop = list.begin(); loop != list.end(); ++loop)
    {
        std::cout &lt;&lt; *loop &lt;&lt; "\n";
    }
}


Diagram of Node Insertion:

Node Before Insertion Starts

      after                                        
      #########                         #########   
   --&gt;#  Next #------------------------&gt;#  Next #----
      #       #                         #       #
   ---#Prev   #&lt;------------------------#Prev   #&lt;---
      #########                         #########    

                       NewNode(this)
                       #########
                       #   Next#
                       #Prev   #
                       #########


prev          = after;

      after
      #########                         #########   
   --&gt;#  Next #------------------------&gt;#  Next #----
      #       #                         #       #
   ---#Prev   #&lt;------------------------#Prev   #&lt;---
      #########   |                     #########    
                  |
                  |    (this)
                  |    #########
                  |    #   Next#
                  -----#Prev   #
                       #########


next          = after->next;

      after
      #########                         #########   
   --&gt;#  Next #------------------------&gt;#  Next #----
      #       #                  |      #       #
   ---#Prev   #&lt;-----------------|------#Prev   #&lt;---
      #########   |              |       #########    
                  |              |
                  |    (this)    |
                  |    ######### |
                  |    #   Next#--
                  -----#Prev   #
                       #########


prev->next    = this;

      after
      #########                         #########   
   --&gt;#  Next #------            ------&gt;#  Next #----
      #       #     |            |      #       #
   ---#Prev   #&lt;----|------------|------#Prev   #&lt;---
      #########   | |            |      #########    
                  | |            |
                  | |  (this)    |
                  | |  ######### |
                  | --&gt;#   Next#--
                  -----#Prev   #
                       #########


next->prev    = this;

      after
      #########                         #########   
   --&gt;#  Next #------            ------&gt;#  Next #----
      #       #     |            |      #       #
   ---#Prev   #&lt;--- |            |   ---#Prev   #&lt;---
      #########   | |            |   |  #########    
                  | |            |   |
                  | |  (this)    |   |
                  | |  ######### |   |
                  | --&gt;#   Next#--   |
                  -----#Prev   #&lt;-----
                       #########