Parece que tanto static_cast como reinterpret_cast funcionan bien para convertir void * a otro tipo de puntero. ¿Hay una buena razón para favorecer a uno sobre el otro?
202
Parece que tanto static_cast como reinterpret_cast funcionan bien para convertir void * a otro tipo de puntero. ¿Hay una buena razón para favorecer a uno sobre el otro?
Respuestas:
Uso
static_cast
: es el modelo más estrecho que describe exactamente qué conversión se realiza aquí.Existe la idea errónea de que usar
reinterpret_cast
sería una mejor combinación porque significa "ignorar completamente la seguridad de tipo y simplemente lanzar de A a B".Sin embargo, esto en realidad no describe el efecto de a
reinterpret_cast
. Más bien,reinterpret_cast
tiene una serie de significados, para todos los cuales sostiene que "el mapeo realizado porreinterpret_cast
está definido por la implementación". [5.2.10.3]Pero en el caso particular de echar de
void*
aT*
la cartografía es completamente bien definido por la norma; a saber, asignar un tipo a un puntero sin tipo sin cambiar su dirección.Esta es una razón para preferir
static_cast
.Además, y posiblemente más importante, es el hecho de que cada uso de
reinterpret_cast
es francamente peligroso porque convierte cualquier cosa en otra cosa realmente (para punteros), mientras questatic_cast
es mucho más restrictivo, proporcionando así un mejor nivel de protección. Esto ya me ha salvado de errores en los que accidentalmente intenté forzar un tipo de puntero a otro.fuente
Esta es una pregunta difícil. Por un lado, Konrad hace un excelente comentario sobre la definición de especificaciones para reinterpret_cast , aunque en la práctica probablemente haga lo mismo. Por otro lado, si está convirtiendo entre tipos de puntero (como es bastante común al indexar en la memoria a través de un char *, por ejemplo), static_cast generará un error de compilador y se verá obligado a usar reinterpret_cast todos modos.
En la práctica, uso reinterpret_cast porque es más descriptivo de la intención de la operación de transmisión. Ciertamente, podría hacer un caso para que un operador diferente designe reinterpretaciones de puntero solamente (lo que garantiza la misma dirección devuelta), pero no hay una en el estándar.
fuente
reinterpret_cast
!Sugiero usar siempre el molde más débil posible.
reinterpret_cast
se puede usar para lanzar un puntero a afloat
. Cuanto más se rompe la estructura del elenco, más atención requiere usarlo.En caso de
char*
, usaría el molde de estilo c, hasta que tengamos algoreinterpret_pointer_cast
, porque es más débil y nada más es suficiente.fuente
float f = *reinterpret_cast<const float*>(&p);
float
, lo cual es falso. Los moldes de expresiónvoid **
aconst float *
, y luego utiliza una operación de eliminar la referencia (que no es un elenco), para convertirconst float *
afloat
.Mi preferencia personal se basa en la alfabetización de código como esta:
o
Ambos hacen lo mismo al final, pero static_cast parece más apropiado en un entorno de aplicaciones de middleware, mientras que reinterpretar cast parece más como algo que verías en una biblioteca de nivel inferior en mi humilde opinión.
fuente