Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Isn't an Iterator in c++ a kind of a pointer?

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?

like image 395
Bilthon Avatar asked Apr 18 '10 03:04

Bilthon


3 Answers

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
    }
} 
like image 107
Eclipse Avatar answered Oct 04 '22 22:10

Eclipse


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.

like image 41
rlbond Avatar answered Oct 04 '22 20:10

rlbond


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;
like image 31
Stephen Avatar answered Oct 04 '22 22:10

Stephen