2011-12-08 14 views
7

Tengo la siguiente función de plantilla utilizada para volcar datos de cualquier tipo estándar en una secuencia de salida binaria.molde de estilo c vs reinterpret_cast

template<typename T> static void 
dump (const T& v, ostream& o) { 
    o.write (reinterpret_cast<const char*>(&v), sizeof(T)); 
} 

En lugar de la reinterpret_cast, también podría usar un estilo C (const char *). ¿Hay alguna razón en particular para usar reinterpret_cast? Leí algunas otras publicaciones donde reinterpret_cast fue mal visto. Pero el uso anterior es legal y no puede ser reemplazado por nada más, ¿verdad?

Gracias

+0

Supongo que conoce la consecuencia de hacer eso (que el archivo resultante solo puede ser leído por el programa compilado con las mismas opciones con el mismo compilador en la misma arquitectura). – curiousguy

+0

Alguien me va a golpear por decir esto, pero si * quieres * usar moldes estilo C, siempre puedes dejar un comentario radical genérico que simplemente no puedes perderte. Tuvo que * alguna * manera de encontrar su 'const's en C, también. ¯ | _ (ツ) _ | ¯ Por supuesto, debes tener en cuenta los peligros. –

Respuesta

10

El problema con yesos C-Style es que lo hacen mucho bajo el capó. Consulte aquí para obtener una explicación detallada: http://anteru.net/2007/12/18/200/

Debería tratar de usar siempre los modelos C++, hace la vida más fácil a largo plazo. El principal problema con los moldes de estilo C en este caso es que podría haber escrito (char*)(&v) mientras que con reinterpret_cast, necesitaría un const_cast adicional, por lo que es un poco más seguro. Además, puede encontrar fácilmente reinterpret_cast con una expresión regular, que no es posible para los modelos de estilo C.

+2

Ni siquiera necesita una expresión regular completa para 'reinterpret_cast', basta con una simple búsqueda de texto (buena ol '" Buscar "en la mayoría de los editores) :) –

+3

Args, sí. Empecé diciendo que no se puede regexar para un molde de estilo C, y luego la oración terminó al revés;) – Anteru

+0

¿Querría encontrar todos los repartos? – curiousguy

1

reinterpret_cast está mal visto cuando se utiliza para reemplazar un static_cast o dynamic_cast. Se recomienda usarlo para reemplazar un lanzamiento de C.

Los nuevos moldes tienen ventajas sobre los moldes de estilo C. Por un lado, puede limitar lo que realmente desea, por otro, es mucho más fácil hacer una búsqueda textual para los nuevos moldes que para los moldes en C.

+1

"_hacer una búsqueda textual de los nuevos casts_" ¿con qué frecuencia ha hecho eso? – curiousguy

+0

@curiousguy: Lo he hecho algunas veces. Casi nunca me importa que obtuve algo de un elenco, pero a menudo me importa que di un paso en particular que casualmente sé que involucra una operación de reparto. No estoy buscando el elenco, * per se *, estoy buscando algo más que sepa que usé un elenco. –

4

No hay diferencia. En la situación dada, el elenco de estilo C es precisamente una transmisión de "reinterpretación".

La razón por la que deberías preferir los moldes de estilo C++ es que son explícitos sobre lo que están emitiendo. Un elenco de estilo C siempre tratará de recurrir al elenco más crudo posible, mientras que el elenco de estilo de C++ solo se compila si es posible según lo previsto: un reparto estático solo tiene éxito si los valores son convertibles o los punteros/referencias son compatibles, y un molde de fusión solo funciona si el origen y el destino son versiones cv-qualified uno del otro. Una reinterpretación establece explícitamente que desea examinar una representación binaria subyacente. (Tenga en cuenta que los únicos válidos reinterpretar-moldes suelen ser los - que invalidaría o char-puntero, a menos que sean parte de algún truco más grande.)

+0

"_Tenga en cuenta que los únicos reinterpretes válidos son aquellos que anulan-() puntero_" ¿por qué querría lanzar a 'void *'? – curiousguy

+0

@curiousguy: placement-new ... –

+0

No necesita 'reinterpret_cast' aquí; 'static_cast' está bien. (Me hubiera gustado un estándar 'implicit_cast'.) – curiousguy

3

fundición de estilo C es muy muy peligroso. Así que C++ categórico dividió el casting a los siguientes tipos basados ​​en el uso típico,

dynamic_cast (expresión) - Permite la conversión entre la clase jerárquica adecuada.

const_cast (expresión) - Expulsa la const-ness.

static_cast (expresión) - Hasta cierto punto de estilo C, pero respeta algunas incompatibilidades entre tipos y no permite.

reinterpret_cast (expresión) - Si todavía no se cumple el requisito, esto está disponible. Fundición de estilo C pero con un nombre. Por lo tanto, será fácil encontrarlo en una gran base de código.

Nota: - La mayoría de "reinterpret_cast" puede eliminarse con el diseño adecuado. En otras palabras, "reinterpret_cast" es necesario significa, lo más probable es que algo esté mal en el diseño.

Actualización: Esta debería ser la última opción, y en el caso anterior, el uso es correcto. Ahora, mencionar reinterpret_cast dará al lector la impresión de que intencionalmente el escritor ha elegido no preocuparse por la seguridad del tipo. Pero usar el estilo c no dará esa impresión.

+0

Pero supongo que el reinterpret_cast utilizado en el código anterior es muy sencillo, ¿y no califica para su nota de rediseño? – shekhar

+0

Como mencioné, esta debería ser la última opción, y en el caso anterior, el uso es correcto. Ahora, mencionar reinterpret_cast dará al lector la impresión de que intencionalmente el escritor ha elegido no preocuparse por la seguridad del tipo. Pero usar el estilo c no dará esa impresión. – rakesh