En algunos casos, como el descrito, el Estándar C ++ permite a los compiladores procesar construcciones de la manera que sus clientes encuentren más útil, sin requerir que ese comportamiento sea predecible. En otras palabras, tales construcciones invocan "Comportamiento indefinido". Sin embargo, eso no implica que tales construcciones estén "prohibidas" ya que el Estándar C ++ renuncia explícitamente a la jurisdicción sobre lo que los "programas bien formados" tienen permitido hacer. Si bien no conozco ningún documento de Fundamento publicado para el Estándar C ++, el hecho de que describa el Comportamiento indefinido al igual que C89 sugiere que el significado deseado es similar: "El comportamiento indefinido otorga al implementador la licencia para no detectar ciertos errores del programa que son difíciles diagnosticar.
Hay muchas situaciones en las que la forma más eficiente de procesar algo implicaría escribir las partes de una estructura por las que se preocupará el código descendente, mientras se omiten las que no le importan al código descendente. Exigir que los programas inicialicen a todos los miembros de una estructura, incluidos los que nada les importará, obstaculizaría innecesariamente la eficiencia.
Además, hay algunas situaciones en las que puede ser más eficiente que los datos no inicializados se comporten de manera no determinista. Por ejemplo, dado:
struct q { unsigned char dat[256]; } x,y;
void test(unsigned char *arr, int n)
{
q temp;
for (int i=0; i<n; i++)
temp.dat[arr[i]] = i;
x=temp;
y=temp;
}
Si el código descendente no se preocupa por los valores de ningún elemento de x.dat
o y.dat
cuyos índices no figuran en la lista arr
, el código podría optimizarse para:
void test(unsigned char *arr, int n)
{
q temp;
for (int i=0; i<n; i++)
{
int it = arr[i];
x.dat[index] = i;
y.dat[index] = i;
}
}
Esta mejora en la eficiencia no sería posible si los programadores tuvieran que escribir explícitamente todos los elementos temp.dat
, incluidos aquellos que no están interesados, antes de copiarlo.
Por otro lado, hay algunas aplicaciones en las que es importante evitar la posibilidad de fuga de datos. En tales aplicaciones, puede ser útil tener una versión del código que esté instrumentada para atrapar cualquier intento de copiar almacenamiento no inicializado sin tener en cuenta si el código posterior lo vería, o podría ser útil tener una garantía de implementación que garantice cualquier almacenamiento cuyos contenidos podrían filtrarse se pondrían a cero o se sobrescribirían con datos no confidenciales.
Por lo que puedo decir, el estándar C ++ no intenta decir que ninguno de estos comportamientos es lo suficientemente más útil que el otro como para justificar su mandato. Irónicamente, esta falta de especificación puede estar destinada a facilitar la optimización, pero si los programadores no pueden explotar ningún tipo de garantías de comportamiento débiles, cualquier optimización se negará.