Dans certains cas, comme celui décrit, la norme C ++ permet aux compilateurs de traiter les constructions de la manière que leurs clients trouveraient la plus utile, sans exiger que ce comportement soit prévisible. En d'autres termes, ces constructions invoquent un "comportement indéfini". Cela n'implique pas, cependant, que de telles constructions sont censées être "interdites" puisque la norme C ++ renonce explicitement à la juridiction sur ce que les programmes bien formés sont "autorisés" à faire. Bien que je ne sois au courant d'aucun document de justification publié pour la norme C ++, le fait qu'il décrit un comportement indéfini, tout comme le fait C89, suggère que la signification voulue est similaire: diagnostiquer.
Il existe de nombreuses situations où le moyen le plus efficace de traiter quelque chose impliquerait d'écrire les parties d'une structure dont le code en aval va se soucier, tout en omettant celles dont le code en aval ne se souciera pas. Exiger que les programmes initialisent tous les membres d'une structure, y compris ceux dont personne ne se souciera jamais, entraverait inutilement l'efficacité.
De plus, dans certaines situations, il peut être plus efficace de faire en sorte que les données non initialisées se comportent de manière non déterministe. Par exemple, étant donné:
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 le code en aval ne se soucie pas des valeurs des éléments de x.dat
ou y.dat
dont les indices ne sont pas répertoriés dans arr
, le code peut être optimisé pour:
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;
}
}
Cette amélioration de l'efficacité ne serait pas possible si les programmeurs étaient tenus d'écrire explicitement tous les éléments de temp.dat
, y compris ceux en aval qui ne se soucient pas, avant de le copier.
D'un autre côté, il existe certaines applications où il est important d'éviter la possibilité de fuite de données. Dans de telles applications, il peut être utile d'avoir une version du code qui est instrumentée pour intercepter toute tentative de copier le stockage non initialisé sans se soucier de savoir si le code en aval le regarderait, ou il pourrait être utile d'avoir une garantie d'implémentation que tout stockage dont le contenu pourrait être divulgué serait mis à zéro ou remplacé par des données non confidentielles.
D'après ce que je peux dire, le standard C ++ ne tente pas de dire que l'un de ces comportements est suffisamment plus utile que l'autre pour justifier son mandat. Ironiquement, ce manque de spécification peut être destiné à faciliter l'optimisation, mais si les programmeurs ne peuvent exploiter aucune sorte de garanties comportementales faibles, toutes les optimisations seront annulées.