operadores - static_cast c++ español
¿Es legal lanzar un puntero a la matriz de referencia usando static_cast en C++? (1)
Tengo un puntero T * pValues
que me gustaría ver como T (&values)[N]
En esta respuesta SO https://stackoverflow.com/a/2634994/239916 , la forma propuesta de hacerlo es
T (&values)[N] = *static_cast<T(*)[N]>(static_cast<void*>(pValues));
La preocupación que tengo sobre esto es. En su ejemplo, pValues
se inicializa de la siguiente manera
T theValues[N];
T * pValues = theValues;
Mi pregunta es si el constructo de pValues
es legal si pValues
proviene de cualquiera de los siguientes constructos:
1:
T theValues[N + M]; // M > 0
T * pValues = theValues;
2:
T * pValues = new T[N + M]; // M >= 0
Respuesta corta: tienes razón. El yeso es seguro solo si pValues
es de tipo T[N]
y los dos casos que mencionas (diferente tamaño, matriz dinámicamente asignada) muy probablemente conduzcan a un comportamiento indefinido .
Lo bueno de static_cast
es que se static_cast
algunas comprobaciones adicionales en tiempo de compilación, por lo que si parece que estás haciendo algo mal, el compilador se quejará (en comparación con el feo estilo C que te permite hacer casi cualquier cosa), por ejemplo:
struct A { int i; };
struct C { double d; };
int main() {
A a;
// C* c = (C*) &a; // possible to compile, but leads to undefined behavior
C* c = static_cast<C*>(&a);
}
le dará: invalid static_cast from type ''A*'' to type ''C*''
En este caso, se lanza a void*
, que desde la vista de los controles que se pueden realizar en tiempo de compilación es legal para casi cualquier cosa, y viceversa: void*
puede devolverse a casi cualquier cosa, lo que hace que el uso de static_cast
completamente inútil en el primer lugar ya que estas verificaciones se vuelven inútiles.
Para el ejemplo anterior:
C* c = static_cast<C*>(static_cast<void*>(&a));
no es mejor que:
C* c = (C*) &a;
y lo más probable es que conduzca a un uso incorrecto de este puntero y comportamiento indefinido con él.
En otras palabras:
A arr[N];
A (&ref)[N] = *static_cast<A(*)[N]>(&arr);
es seguro y está bien. Pero una vez que comienzas a abusar de static_cast<void*>
no hay garantías en absoluto sobre lo que sucederá realmente porque incluso cosas como:
C *pC = new C;
A (&ref2)[N] = *static_cast<A(*)[N]>(static_cast<void*>(&pC));
se vuelve posible