2010-04-18 16 views
5

Ok, esta vez decidí hacer una lista usando el STL. Necesito crear un socket TCP dedicado para cada cliente. Así que cada vez que tengo una conexión, instauro un socket y agrego un puntero a él en una lista.¿No es un iterador en C++ una especie de puntero?

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. 

Poner un nuevo puntero a una toma de corriente fue fácil, pero ahora cada vez que termina la conexión que debería desconectar el enchufe y eliminar el puntero de modo que no se deje una enorme pérdida de memoria, ¿verdad? así .. Yo pensaba que estaba haciendo bien mediante el establecimiento de esto:

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; 
    } 
} 

Pero el compilador está diciendo esto:

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

¿Puede alguien ayudarme aquí? pensé que estaba haciendo las cosas bien, ¿no es un iterador en un momento dado simplemente señalando uno de los elementos del conjunto? ¿Cómo puedo arreglarlo?

+1

El iterador _puntos_ a un elemento en el contenedor, por lo que debe desreferenciarlo usando el operador *. – jweyrich

+7

Es más fácil pensar en un puntero como en un tipo de iterador de acceso aleatorio ... uno que ve toda la RAM como un gran vector. –

Respuesta

18

Prueba esto:

pSocket = *it; 

Iteradores actuar mucho como punteros, pero en realidad puede ser un puntero o una clase de pleno derecho que actúa como tal. Lo importante en este caso, es que cuando desreferencia uno, obtiene cualquier elemento que se almacena en el contenedor. Dado que está almacenando MyTcp* s en la lista, cuando desreferencia el iterador obtendrá un MyTcp*. pSocket es del tipo MyTcp* por lo que la asignación anterior tiene éxito. La asignación que está tratando de hacer no es desreferenciar el iterador; está tratando de asignar el iterador mismo al pSocket.

Es algo así como el siguiente caso:

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 
    } 
} 
+0

@Eclipse: [sobre punteros e iteradores] "cuando desreferencia uno, obtiene cualquier elemento que se almacena en el contenedor ..." ¿No es lo mismo con los punteros? * ¿Hay ALGUNA diferencia entre punteros e iteradores de C++? * – Lazer

+0

@eskay: Puedes pensar en punteros como un tipo de iterador, específicamente un "iterador de acceso aleatorio" sobre la memoria en bruto. ver http://www.sgi.com/tech/stl/RandomAccessIterator.html para el requisito de ese tipo de iterador. En general, sin embargo, los iteradores pueden ser clases enteras que hacen toda clase de cosas alocadas dentro de sus operadores '++' y '*'. Consulte boost.Iterator (http://www.boost.org/doc/libs/1_42_0/libs/iterator/doc/index.html) para obtener una idea de algunas de las cosas que los iteradores realmente pueden hacer. – Eclipse

+0

Solo un último ejemplo: std :: list en sí es una lista doblemente vinculada. Cada elemento de la lista se almacena de forma individual/independiente en algún lugar del montón, por lo que el iterador necesita algún tipo de puntero al nodo de la lista actual. operator ++ entonces no puede realizar ningún tipo de adición simple, sino que debe establecer su propio puntero de nodo al valor al que apunta el puntero 'siguiente' del nodo apuntado. (Oh, way, many 'point's ...) Entonces, en realidad, no es simplemente un puntero, sino una clase completa envuelta alrededor del puntero real (el puntero debería ser el único dato necesario, así que el tamaño del iterador y el puntero debería ser el mismo). – Aconcagua

4

Un iterador puede ser implementado por un puntero (en el caso del vector, que es). Los iteradores tienen semántica de puntero; los desreferenciamos para obtener el valor.

Pero está almacenando punteros en la lista. El "MyTcp *" es su valor, por lo tanto, para asignarlo, desreferencia "it".

pSocket = *it; 
+0

Los iteradores de vectores no son siempre punteros. –

3

Un iterador se limita a señalar a uno de los elementos, y la sintaxis para la eliminación de referencias es el mismo, pero es un tipo diferente (con una representación diferente en memoria), y la aritmética de punteros en él hace algo diferente de lo que hace en un puntero (es decir, el resultado de los puntos aritméticos del iterador en una ubicación de memoria diferente a la que obtendría si convirtiera el iterador en un puntero y lo hiciera aritmético), por lo que generalmente no quiere confundir los dos tipos.

Sin embargo, dados los tipos de que su lista es una lista de punteros, y que sólo está dereferencing pSocket una vez en la llamada pSocket->Disconnect();, creo que la respuesta de Eclipse es lo que quiere: pSocket = *it;

6

Un iterador es una generalización de un puntero. Hay un buen artículo en Wikipedia en el Patrón del iterador.

La razón por la cual los iteradores se utilizan en el STL es para hacer algoritmos ortogonales a los contenedores. Cualquier contenedor se puede usar con (casi) cualquier algoritmo, siempre que ese contenedor admita iteradores.

Cuestiones relacionadas