Pointers for struct and `for` I know something about pointers, but I'm trying to check my knowledge on a sample.  Can somebody check if my code is good?  I don't think that I should use pointers in these structs.

The second question is: Can I use a for loop like this?

for(DLList* i=first; i!=0; i=i-&gt;next)


Is it correct?

struct Node
{
    int id;
    int dist;
    Node* prev;
    vector&lt;Edge*&gt; edges;
};

struct Edge
{
    int length;
    Node* to;
};

struct DLList
{
    DLList *next;
    DLList *prev;
    Node* val;
};


struct DList
{
    DLList *first,*last;

    DList()
    {
        first = 0; 
        last = 0;
    }

    DLList* add(Node* n)
    {
        DLList *newNode = new DLList;
        if(first == 0)
        {
            newNode-&gt;val = n;
            newNode-&gt;next = 0;
            newNode-&gt;prev=0;
            first =  newNode;
            last = newNode;     
        }
        else
        {
            newNode-&gt;val = n;
            newNode-&gt;next = 0;
            newNode-&gt;prev=last;
            last = newNode;
            last-&gt;next=newNode;
        }
        return last;
    }

    void removeFirst()
    {
        if(first!=0)
        {
            first = first-&gt;next;
            if(first != 0)
            {
                first-&gt;prev = 0;        
            }   
        }
    }

    void remove(DLList* e)
    {
        if(e==0)
        {
            return;
        }
        else if(e==first)
        {   
            removeFirst();
        }
        else if(e==last)
        {
            last = last-&gt;prev;
            last -&gt; next = 0;
        }
        else
        {
            e-&gt;prev-&gt;next = e-&gt;next;
            e-&gt;next-&gt;prev = e-&gt;prev;
        }
    }

    void remove(Node* n)
    {
        if(first == 0)
        {
            return;     
        }
        if(n==first-&gt;val)
        {
            removeFirst();
        }
        else if(n==last-&gt;val)
        {
            last = last-&gt;prev;
            last-&gt;next = 0; 
        }
        else
        {
            for(DLList* i=first; i!=0; i=i-&gt;next)
            {
                if(n==i-&gt;val)
                {   
                    i-&gt;prev-&gt;next = i-&gt;next;
                    i-&gt;next-&gt;prev = i-&gt;prev;
                    break;
                }       
            }   
        }
    }

    bool isEmpty()
    {
        return first == 0;
    } 

};
I'm assuming that this is basically a pointer exercise rather than a real piece of code that you're planning to use.  If it's the latter, please reconsider -- there are STL containers that do this better and safer.  As to your question about the for loop, there's nothing wrong with that if you're using pointers.  In fact it's a pretty common idiom in C.

Don't abuse using namespace std

Putting using namespace std at the top of every program is a bad habit that you'd do well to avoid.  I don't know that you're doing that, but the use of vector in the definition of Node suggests it.

Use nullptr

Every instance of 0 in your code would probably more correctly be encoded as nullptr as defined in C++11.  If you're using an older compiler, you can use NULL instead which will more clearly indicate to readers of your code that these are pointers.

Reconsider the interface

If this is a pointer exercise, that's fine, but if you actually intend to use this for something, you should probably reconsider the interface.  Specifically, passing around raw pointers is not generally a good idea in C++.  Better would be to use unique_ptr (C++11) or auto_ptr (C++03).

Also the version of remove() that takes a linked list node pointer as an argument is a very dangerous thing to have in an interface.  Knowledge of a node's structure would be better encapsulated within the class and not revealed as part of the interface.

Use better names

Having DLList as the name of a class implementing a doubly-linked list makes sense, but having that actually be the name of an individual node in such a list does not.  Instead of DList and DLList, it would be much easier to interpret your code if they were named DLList and DLListNode.  Also the function add suggests that the node is added to the end, but the code actually prepends this to the list which is, at best, confusing.

Simplify remove(Node* n)

The remove(Node *n) is more complex than it needs to be.  It could be rewritten as:

void remove(Node* n)
{
    for(DLListNode* i=first; i!=nullptr; i=i-&gt;next)
    {
        if(n==i-&gt;val)
        {   
            i-&gt;prev-&gt;next = i-&gt;next;
            i-&gt;next-&gt;prev = i-&gt;prev;
            break;
        }       
    }   
}


Note that this still has a bug just like the original.  What happens if i-&gt;prev or i-&gt;next are null pointers?  You should handle those cases.

A similar simplification could be done for the other remove functions.

Don't leak memory

Your program uses new but not delete which is a surefire recipe for memory leaks. 

Be explicit about whether your container owns contained objects

It's not clear (because there are not comments) whether the contained Node objects should be destroyed or not when either of the two remove functions is called.

Define a destructor

Because you have a constructor, you really should define a destructor as well.  See the note above about leaking memory.

Consider using an anchor node

Much of the special-case checking for null pointers in your code would disappear if you defined an anchor or head node in the constructor.  In that case, there would always be one node and you wouldn't have to check for null pointers quite as often.