views:

248

answers:

4

Ok this time I decided to make a list using the STL. I need to create a dedicated TCP socket for each client. So everytime I've got a connection, I instantiate a socket and add a pointer to it on a list.

list<MyTcp*> SocketList;  //This is the list of pointers to sockets
list<MyTcp*>::iterator it;  //An iterator to the list of pointers to TCP sockets.

Putting a new pointer to a socket was easy, but now every time the connection ends I should disconnect the socket and delete the pointer so I don't get a huge memory leak, right? well.. I thought I was doing ok by setting this:

it=SocketList.begin();
while( it != SocketList.end() ){
    if((*it)->getClientId() == id){
    pSocket = it; //    <-------------- compiler complains at this line
    SocketList.remove(pSocket);
    pSocket->Disconnect();
    delete pSocket;
    break;
    }
}

But the compiler is saying this:

 error: invalid cast from type ‘std::_List_iterator<MyTcp*>’ to type ‘MyTcp*’

Can someone help me here? i thought I was doing things right, isn't an iterator at any given time just pointing to one of the elements of the set? how can I fix it?

+13  A: 

Try this:

pSocket = *it; 

Iterators act a lot like pointers, but in reality they can be a pointer or a full-fledged class that acts like one. The important thing in this case, is that when you dereference one, you get whatever item is being stored in the container. Since you are storing MyTcp*s in the list, when you dereference the iterator you get a MyTcp*. pSocket is of type MyTcp* so the assignment above succeeds. The assignment you are trying to do is not dereferencing the iterator -- you are trying to assign the iterator itself to pSocket.

It's kind of like the following case:

void foo()
{
    MyTcp *array[10]; // An array full of MyTcp pointers
    MyTcp **iterator = NULL; // pointers make good iterators for arrays (but not for std::lists)
    for (iterator = array; iterator != array + 10; ++iterator)
    {
        // This fails to compile (cannot assign MyTcp** to MyTcp*:
        MyTcp *wrong = iterator;            

        // This succeeds:
        MyTcp *current = *iterator; // important to dereference the iterator
    }
} 
Eclipse
@Eclipse: [about pointers and iterators] "when you dereference one, you get whatever item is being stored in the container..." Isn't it the same with pointers? *Is there ANY difference at all between pointers and C++ iterators?*
Lazer
@eskay: You can think of pointers as a type of iterator - specifically a "Random Access Iterator" over raw memory. see http://www.sgi.com/tech/stl/RandomAccessIterator.html for the requirement of that type of iterator. In general though, iterators can be entire classes that do all sorts of crazy things inside their `++` and `*` operators. See boost.Iterator (http://www.boost.org/doc/libs/1_42_0/libs/iterator/doc/index.html) for an idea of some of the things iterators can really do.
Eclipse
+4  A: 

An iterator might be implemented by a pointer (in the case of vector, it is). Iterators do have pointer semantics - you dereference them to get at the value.

But you're storing pointers in the list. The "MyTcp*" is your value, so to assign it, you dereference "it".

pSocket = *it;
Stephen
+3  A: 

An iterator does just point to one of the elements, and the syntax for dereferencing it is the same, but it's a different type (with a different in-memory representation), and pointer arithmetic on it does something different than it does on a pointer (i.e. the result of iterator arithmetic points to a different memory location than you'd get if you converted the iterator to a pointer and did pointer arithmetic), so you usually don't want to confuse the two types.

However, given the types that your list is a list of pointers, and you're only dereferencing pSocket once in the pSocket->Disconnect(); call, I think Eclipse's answer is what you want: pSocket = *it;

Ken Bloom
+3  A: 

An iterator is a generalization of a pointer. There's a good article in Wikipedia on the Iterator Pattern.

The reason iterators are used in the STL is to make algorithms orthogonal to containers. Any container can be used with (nearly) any algorithm as long as that container supports iterators.

rlbond