Doubly circular linked list implementation I made this C++ doubly circular linked list implementation and it seems to work right, handle everything well, and not have any errors. However, I've been working with it for a while and would like some fresh eyes to take a look and see if I am missing anything large or if my code contains any 'gotchas'. 

Side note: I ran valgrind on several tests of this implementation and never got any memory leaks so I suspect it is handling that end of this correctly.

CLL.h

#ifndef CLL
#define CLL

class CircularLinkedNode {
public:
    int info;
    CircularLinkedNode *next, *prev;

    CircularLinkedNode() {
        next = prev = this;
    }

    CircularLinkedNode(int num) {
        info = num;
        next = prev = this;
    }

    CircularLinkedNode(int nu, CircularLinkedNode *ne, CircularLinkedNode *pre) {
        info = nu;
        //auto put new node in the middle of next and previous
        next = ne;
        prev = pre;
        prev-&gt;next = this;
        next-&gt;prev = this;
    }

    ~CircularLinkedNode() {
        //when deleted, seal the gap
        //prev-&gt;next = next;
        //next-&gt;prev = prev;
    }
};

class CircularLinkedList {
private:
    CircularLinkedNode *head, *tail;
public:
    CircularLinkedList() {
        head = tail = 0;
    }

    ~CircularLinkedList();

    bool isEmpty() const {
        return head == 0;
    }

    void addToHead(int);
    void addToTail(int);
    int removeFromHead();
    int removeFromTail();
    void remove(int);
    bool isInList(int) const;


};

#endif


CLL.cpp

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


CircularLinkedList::~CircularLinkedList() {
if (isEmpty()) {
    return;
}
if(head == tail) {
    delete head;
    head = tail = 0;
    return;
}

    CircularLinkedNode *tmp = head-&gt;next;
    delete head;
    while(tmp != tail) {
        head = tmp;
        tmp = tmp-&gt;next;
        delete head;
    }
    delete tail;

}

void CircularLinkedList::addToHead(int n) {
    isEmpty() ? head = tail = new CircularLinkedNode(n) : head = new     CircularLinkedNode(n, head, tail);
}

void CircularLinkedList::addToTail(int n) {
    isEmpty() ? tail = head = new CircularLinkedNode(n) : tail = new CircularLinkedNode(n, head, tail);
}

int CircularLinkedList::removeFromHead() {
    if(isEmpty()) {
        return 0;
    }

    int el = head-&gt;info;
    if(head == tail) {
        delete head;
        head = 0;
        return el;
    }

    CircularLinkedNode *tmp = head;
    head-&gt;prev-&gt;next = head-&gt;next;
    head-&gt;next-&gt;prev = head-&gt;prev;
    head = head-&gt;next;
    std::cout &lt;&lt; "delete" &lt;&lt; std::endl;
    delete tmp;
    return el;
}

int CircularLinkedList::removeFromTail() {
    if(isEmpty()) {
        return 0;
    }

    int el = tail-&gt;info;
    if(head == tail) {
        delete tail;
        tail = 0;
        return el;
    }
    CircularLinkedNode *tmp = tail;
    tail-&gt;prev-&gt;next = tail-&gt;next;
    tail-&gt;next-&gt;prev = tail-&gt;prev;
    tail = tail-&gt;prev;
    std::cout &lt;&lt; "delete" &lt;&lt; std::endl;
    delete tmp;
    return el;
}

void CircularLinkedList::remove(int n) {
    if (!isEmpty()) {
        if (head-&gt;info == n) {
            removeFromHead();
            return;
        } else if (tail-&gt;info == n) {
            removeFromTail();
            return;
        } else {
            CircularLinkedNode *tmp;
            for (tmp = head; tmp != tail &amp;&amp; !(tmp-&gt;info == n); tmp = tmp-&gt;next);
            if(tmp != tail) {
                tmp-&gt;prev-&gt;next = tmp-&gt;next;
                tmp-&gt;next-&gt;prev = tmp-&gt;prev;
                delete tmp;
            }
        }

    }
}

bool CircularLinkedList::isInList(int el) const {
    CircularLinkedNode *tmp;
    for (tmp = head; tmp != tail &amp;&amp; !(tmp-&gt;info == el); tmp = tmp-&gt;next);
    return (tmp-&gt;info == el);
}
Heads and tails
I got confused reading this code because in my mind, a circular list doesn't have a tail.  Or at least, the tail is the same as the head.
The code appears to be correct, but you could have only kept a head pointer.  Anywhere where you use tail, you could essentially replace that with head-&gt;prev and get the same functionality.