2010-09-13 9 views
5

Estoy desarrollando un motor para transferir el código existente a una plataforma diferente. El código existente se ha desarrollado utilizando una API de terceros, y mi motor redefinirá esas funciones de API de terceros en términos de mi nueva plataforma.¿Debo devolver un iterador o un puntero a un elemento en un contenedor STL?

Las siguientes definiciones proceden de la API:

typedef unsigned long shape_handle;  
shape_handle make_new_shape(int type); 

necesito para redefinir make_new_shape y tengo la opción de redefinir shape_handle.

he definido esta estructura (simplificada):

struct Shape 
{ 
    int type 
}; 

El Llamador de make_new_shape no se preocupa por la estructura subyacente de Shape, sólo se necesita un "manejar" a ella para que pueda llamar a funciones como:

void `set_shape_color(myshape, RED);` 

donde myshape es el identificador de la forma.

Mi motor administrará la memoria para los objetos Shape y otros requisitos determinan que el motor debe almacenar objetos Shape en una lista u otro contenedor iterable.

Mi pregunta es, ¿cuál es la forma más segura de representar este identificador - si el Shape se va a almacenar en una lista estándar - un iterador, un puntero, un índice?

+2

¿Por qué ha elegido std :: list? –

+0

@jk - Necesito poder agregar y eliminar objetos 'Shape' del centro del contenedor. – BeeBand

+0

Definitivamente no quiere redefinir shape_handle (o make_new_shape). –

Respuesta

3

La respuesta depende de su representación:

  • para std::list, utilice un iterator (no un puntero), debido a que un iterator le permite eliminar el elemento sin tener que caminar toda la lista.
  • para std::map o boost::unordered_map, utilice el Key (por supuesto)

Su diseño sería mucho más fuerte si se ha utilizado un contenedor asociativo, porque los contenedores asociativos le dan la posibilidad de consultar la presencia del objeto, en lugar de invocar Comportamiento no definido.

Trate evaluación comparativa tanto map y unordered_map para ver cuál es más rápida en su caso :)

6

Tanto un iterador como un puntero harán cosas malas si intenta acceder a ellos después de que el objeto ha sido eliminado, por lo que ninguno de los dos es intrínsecamente más seguro. La ventaja de un iterador es que puede usarse para acceder a otros miembros de su colección.

Por lo tanto, si solo desea acceder a su forma, entonces un puntero será más simple. Si desea iterar a través de su lista, utilice un iterador.

Un índice es inútil en una lista, ya que std :: list no sobrecarga el operador [].

+1

+1: Si proporciona acceso a su representación interna (iterador) o no (puntero) es la diferencia más importante. –

3

IIF la representación interna será una lista de Formas, luego los punteros y los iteradores son seguros. Una vez que se asigna un elemento, nunca se producirá la reubicación. No recomendaría un índice por razones obvias de rendimiento de acceso. O (n) en caso de listas.

Si estaba usando un vector, entonces no use iteradores o punteros, porque los elementos pueden reubicarse cuando se excede la capacidad de los vectores, y sus punteros/iteradores se volverán inválidos.

Si desea una representación segura independientemente del contenedor interno, cree un contenedor (lista/vector) de punteros a sus formas y devuelva el puntero de forma a su cliente. Incluso si el contenedor se mueve en la memoria, los objetos Shape permanecerán en la misma ubicación.

3

iteradores no son más seguros que los punteros, pero tienen mucho diagnóstico mejor que los punteros primas si está utilizando una comprobado la implementación de STL!

Por ejemplo, en una compilación de depuración, si devuelve un puntero a un elemento de lista, y luego borra ese elemento de lista, tiene un puntero colgante. Si accede, obtiene un bloqueo y todo lo que puede ver es datos no deseados. Eso puede hacer que sea difícil averiguar qué salió mal.

Si usa un iterador y tiene una implementación de STL activada, tan pronto como acceda al iterador a un elemento borrado, recibirá un mensaje como "iterador fue invalidado". Eso es porque borraste el elemento al que apunta. Boom, acabas de ahorrarte potencialmente un montón de esfuerzo de depuración.

Por lo tanto, no índices de rendimiento de O (n). Entre punteros e iteradores - siempre iteradores!

Cuestiones relacionadas