2009-05-10 10 views
9

Me preguntaba, ¿cómo se establece la igualdad (==) para los iteradores de STL? ¿Es una comparación de puntero simple (y por lo tanto basada en direcciones) o algo más elegante?¿Cómo se establece la igualdad del iterador STL?

Si tengo dos iteradores de dos objetos de lista diferentes y los comparo, ¿el resultado siempre será falso?

¿Qué tal si comparo un valor válido con uno que está fuera de rango? ¿Eso siempre es falso?

Respuesta

11

Las clases de iterador pueden definir operadores sobrecargados ==, si así lo desean. Entonces, el resultado depende de la implementación de operator==.

No se supone que realmente deba comparar iteradores de contenedores diferentes. Creo que algunas implementaciones de depuración de STL señalarán una advertencia si haces esto, lo que te ayudará a detectar casos de este uso erróneo en tu código.

+6

¿En realidad no se supone que deba hacerlo? ¡Sin duda no debes! – xtofl

+0

La capacidad de comparar iteradores de diferentes contenedores hace que MSVC emita una advertencia de obsolescencia molesta al usar 'std :: copy' ... –

2

Me preguntaba, ¿cómo se establece la igualdad (==) para los iteradores de STL?

No se pueden comparar todos los iteradores (p. Ej., Los Iteradores de salida no están obligados a proporcionar op==). Puede usar el operator== cuando el concepto de un rango está bien definido para la categoría de iterador bajo consideración.

¿Es una comparación de puntero simple (y por lo tanto en función de las direcciones) o algo más elegante?

Los iteradores siempre se implementan con punteros. Editar: digo implementado con - que no se refiere a un requisito estándar sino a la práctica de usar poitners como la construcción subyacente. Sin embargo, las implementaciones (como VS) pueden tener controles de validación especiales insertados.

Si tengo dos iteradores de dos objetos de lista diferentes y los comparo, ¿el resultado siempre será falso?

Estás invocando Undefined Behavior.

¿Qué tal si comparo un valor válido con uno que está fuera de rango? ¿Eso siempre es falso?

Nuevamente, invocará a UB. La única comparación válida es entre dos iteradores en el mismo rango o entre uno en el rango y otro en uno pasado el último elemento. Tenga en cuenta que solo puede comparar el iterador con el último elemento, eliminando la referencia de los mismos clientes a UB.

+4

" Los iteradores siempre se implementan como punteros ". No creo que insert_iterator sea un simple puntero.Esperaría que fuera un objeto que contiene un puntero o referencia a un contenedor, más un iterador en ese contenedor. –

+0

. Búscalo. Las implementaciones que he visto utilizan un puntero al contenedor. – dirkgently

+2

Solo se garantiza que std :: vector :: iterator sea convertible a un puntero. Muchos probablemente _use_ punteros a sus nodos. Algunos usan dos punteros. Algunos pueden usar un puntero de archivo. ¿Puedes decir que están implementados como punteros? No lo creo. No me atrevería a basar ningún diseño en eso. – xtofl

1

La prueba de igualdad es específica del tipo de iterador que está utilizando, o puede que no exista. Si realmente desea saber, siempre puede verificar el código fuente de la implementación de STL que está utilizando, busque operador ==() en la clase de iterador.

Los iteradores NO son siempre punteros, y de hecho en algunas versiones "seguras" de STL, nunca son punteros. Los iteradores para vectores y cadenas se implementan comúnmente como punteros porque pueden serlo. Los iteradores para deques, listas, conjuntos y mapas no pueden ser indicadores en ninguna implementación a medias eficiente.

Lo que los iteradores son es un tipo de puntero inteligente. Siguen el principio genérico de que si se ven y se comportan como un puntero, entonces son un puntero en lo que respecta al usuario.

3

Daniel preguntó: Me preguntaba, ¿cómo está (==) estableció la igualdad para los iteradores STL? ¿Es una comparación de puntero simple (y por lo tanto, basada en direcciones) o algo más elegante?

Depende de la implementación. En este momento, en Visual C++ 2008, veo el siguiente código (para el iterador de la lista):

bool operator==(const _Myt_iter& _Right) const 
{ // test for iterator equality 

#if _HAS_ITERATOR_DEBUGGING 
    _Compat(_Right); 
#else 
    _SCL_SECURE_TRAITS_VALIDATE(this->_Has_container() && this->_Same_container(_Right)); 
#endif /* _HAS_ITERATOR_DEBUGGING */ 

    return (_Ptr == _Right._Ptr); 
} 

Verás anterior que existe tanto el código de verificación de la validez iterador, y _Ptr ser un puntero a una nodo de lista.

Así que supongo que hay verificación, y simple, comparación de puntero sin formato.

Daniel preguntó: Si tengo dos iteradores de dos objetos de lista diferentes y los comparo, será el resultado siempre es falsa?

Hasta ahora, parece que el estándar no estaba del todo claro sobre el tema. Al parecer, van a escribir explícitamente que este tipo de operación ha indefinido resultados:

Citando: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#446

El resultado del uso de cualquier operación iterador (24.2.1 [input.iterators], 24.2.2 [output.iterators], 24.2.3 [forward.iterators], 24.2.4 [bidirectional.iterators], 24.2.5 [random.access.iterators]) que utiliza dos valores de iterador como argumentos (nota al pie) que fueron obtenido a partir de dos rangos diferentes r1 y r2 (incluidos sus valores pasados) que no son subrangos de un rango común no está definido, a menos que se describa explícitamente lo contrario.

nota al pie), entre otros estas operaciones son ==, <, binario -, y copiar la asignación

así que supongo que es malo para comparar iterador de diferentes contenedores ... ^ _^

Daniel preguntó: ¿Qué tal si comparo un valor válido con uno que está fuera de rango? ¿Eso siempre es falso?

Igual que el anterior.

Cuestiones relacionadas