Los dos son radicalmente diferentes, al menos en teoría (y posiblemente en unas pocas máquinas raras, en la práctica). El primero toma un puntero a A, y lo convierte en un puntero a B; en teoría, al menos, esto puede implicar cambios en el tamaño y la representación de . (De hecho, he trabajado en máquinas donde char*
era más grande que int*
dudo bastante que todavía existen tales máquinas, aunque tal vez en el mundo incrustado ...). La segunda es realmente el equivalente de *reinterpret_cast<B**>(&pA)
; es toma los bits en pA
, y le dice al compilador que los interprete como a B*
. Si el formato es diferente, mala suerte, y si el tamaño es diferente, es probable que solo acceda a parte de pA
o acceda a la memoria que no es parte de pA
.
Además, el primero es un valor r, el segundo es un valor. Por lo tanto, algo gustan:
++ reinterpret_cast<B*>(pA);
es ilegal, pero:
++ reinterpret_cast<B*&>(pA);
no lo es. Esta es una técnica útil para ofuscar el código y obtener punteros desalineados, punteros en el medio de los objetos u otros punteros que no se atreven a eliminar la referencia.
En general, se debe evitar el segundo formulario, pero existen raras excepciones .Posix garantiza que todos los punteros, incluidos los punteros a las funciones (pero no los punteros a los miembros — Posix especifica un C ABI, que no tiene punteros a los miembros), tienen el mismo tamaño y formato, , por lo que se garantiza que la segunda forma trabajo. Y es la única manera en que puede convertir legalmente al regresar void*
por dlsym
en un puntero a una función :
int (*pf)(int);
reinterpret_cast<void*&>(pf) = dlsym(handle, "functionName");
(En C, escribiría:
int (*pf)(int);
*(void**)(&pf) = dlsym(handle, "functionName");
, consulte la official specification). Tales trucos permiten las conversiones entre los tipos de puntero que no están permitidos de otra manera, pero depende de garantías adicionales no en la norma.
¡Gran respuesta Jmaes! –