2011-02-06 20 views
7

There's this other question asking about how comparing pointers is supposed to be interpreted wrt the C++ Std.¿Se permiten punteros como claves en contenedores STL ordenados?

así que me preguntaba lo que el C++ estándar tiene que decir sobre el uso de punteros como claves en la biblioteca estándar ordenado (STL) contenedores - es decir, se tiene permitido tener

std::map<T1*, T2>

y es esto debido a la especificación de std::less o builtin operator <?

+0

Por cierto, ¿quieres usar las direcciones como clave o el valor de las cosas que señalan como clave? En este último caso, deberá proporcionar un comparador personalizado – sellibitze

+0

relacionado: [verificando si el puntero apunta dentro de una matriz] (http://stackoverflow.com/questions/4657976/) – fredoverflow

Respuesta

11

Sí, porque utiliza std::less, que es necesario para obtener un pedido total, incluso si < no lo hace. (< podría tratar diferentes punteros de distintas secuencias como iguales, lo que daría como resultado un comportamiento extraño de map etc. si inserta punteros de diferentes secuencias).

+1

Para expresar esto ligeramente diferente: Para citar a sellibitze de un comentario a una respuesta a continuación: "... es seguro usar punteros como claves en contenedores asociativos. Pero esto no tiene nada que ver con el operador inferior porque std :: menos es el comparador predeterminado para estos contenedores y C++ hace garantías especiales para std :: less en caso de que T sea un tipo de puntero ... " –

-3

Sí. Los punteros son comparables a través del operador <().

Si los punteros no apuntan a los elementos de la misma matriz o elementos dentro del mismo objeto, el estándar C++ dice que el comportamiento no está especificado [expr.rel].

La norma dice que un comportamiento no especificado significa que su implementación está definida [defns.unspecified].

Si su compilador garantiza un orden débil y estricto de los punteros, puede usar cualquier puntero con contenedores asociativos.

La mayoría de los compiladores hacen comparación de punteros al comparar las direcciones de memoria. En la mayoría de las arquitecturas, esta comparación forma un estricto orden débil.

Por lo tanto, es seguro utilizar punteros como teclas.

+0

solo si apuntan a elementos de la misma matriz. El estándar C++ ofrece garantías más sólidas para std :: less, que es el valor predeterminado para contenedores asociativos ordenados – sellibitze

+0

@sellibitze: los punteros no están relacionados con las matrices. Los punteros a elementos de diferentes matrices son menos comparables. – joke

+1

@joke: No, el estándar no permite comparar punteros arbitrarios con '<'. – fredoverflow

0

"Pueden ser válidos pero no lo son" es la respuesta que daría.

Obviamente, existe la cuestión de la comparabilidad que usted plantea, pero la razón por la que no desea es por la falta de gestión de referencias en los punteros "vainilla". Es muy fácil que el objeto se elimine sin que se elimine del contenedor, lo que da como resultado un puntero no válido y una infracción de acceso la próxima vez que acceda a él.

+0

Eso no es necesariamente válido; cosas como unique_ptr o shared_ptr bien pueden proporcionar operadores comparativos basados ​​en el puntero subyacente. – Puppy

3

Me gustaría agregar otra razón para no hacer esto. Si está utilizando punteros de esta manera, y si tiene un error que depende del orden de los elementos de un contenedor, entonces será muy difícil de encontrar. Incluso si su programa parece ser completamente determinista, no lo será. El orden de los elementos en un contenedor depende del algoritmo que utiliza el asignador de memoria, que está completamente fuera de tu control. Si ejecuta el mismo ejemplo varias veces sin reiniciar su programa, algunos pueden fallar y otros pueden tener éxito.

Esta es la voz de la experiencia amarga. Hice esto con un proyecto de depuración una vez, donde tenía contenedores llenos de símbolos de C++. Cuando necesité ordenar los símbolos, terminé con símbolos que son diferentes, pero que tienen el mismo nombre (piensa en funciones sobrecargadas) y que eran idénticos en todo lo demás. Entonces, en este caso los comparé como último recurso con la dirección del objeto de símbolo. Me encontré con varios errores que aparentemente no eran deterministas, donde el no determinismo era causado solo por este fenómeno. A veces se necesitaron más de 10 o 15 intentos para reproducir los problemas. Eventualmente tomé el tiempo para eliminar la clasificación por direcciones, y eso me ahorró muchos problemas a largo plazo.

Dicho esto, no diré que no he hecho esto recientemente. Pero cada vez que lo hago, siento que es un error.

Cuestiones relacionadas