In alcuni casi, come quello descritto, lo standard C ++ consente ai compilatori di elaborare i costrutti in qualunque modo i loro clienti troverebbero più utili, senza richiedere che il comportamento sia prevedibile. In altre parole, tali costrutti invocano "Undefined Behaviour". Ciò non implica, tuttavia, che tali costrutti debbano essere "vietati" poiché lo standard C ++ rinuncia esplicitamente alla giurisdizione su ciò che i "programmi ben formati" sono "autorizzati" a fare. Sebbene non sia a conoscenza di alcun documento di Rationale pubblicato per lo standard C ++, il fatto che descriva un comportamento indefinito come C89 suggerirebbe che il significato previsto è simile: "Il comportamento indefinito dà alla licenza dell'attore di non rilevare alcuni errori del programma che sono difficili diagnosticare.
Ci sono molte situazioni in cui il modo più efficiente di elaborare qualcosa implicherebbe la scrittura delle parti di una struttura di cui il codice a valle si preoccuperà, omettendo quelle a cui il codice a valle non importa. Richiedere che i programmi inizializzino tutti i membri di una struttura, compresi quelli di cui nulla si preoccuperà mai, impedirebbe inutilmente l'efficienza.
Inoltre, ci sono alcune situazioni in cui può essere più efficiente avere dati non inizializzati comportarsi in modo non deterministico. Ad esempio, dato:
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;
}
se al codice downstream non interessano i valori di alcun elemento x.dat
o di y.dat
cui non sono stati elencati gli indici arr
, il codice potrebbe essere ottimizzato per:
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;
}
}
Questo miglioramento dell'efficienza non sarebbe possibile se ai programmatori fosse richiesto di scrivere esplicitamente ogni elemento temp.dat
, compresi quelli a valle, se ne fregerebbe, prima di copiarlo.
D'altra parte, ci sono alcune applicazioni in cui è importante evitare la possibilità di perdita di dati. In tali applicazioni, può essere utile disporre di una versione del codice che sia strumentata per intercettare qualsiasi tentativo di copiare l'archiviazione non inizializzata senza tener conto del fatto che il codice downstream lo guarderebbe, oppure potrebbe essere utile disporre di una garanzia di implementazione che qualsiasi archiviazione i cui contenuti potrebbero essere trapelati verrebbero azzerati o altrimenti sovrascritti con dati non riservati.
Da quello che posso dire, lo standard C ++ non fa alcun tentativo di dire che uno di questi comportamenti è sufficientemente più utile dell'altro da giustificarlo. Ironia della sorte, questa mancanza di specifiche può essere intesa a facilitare l'ottimizzazione, ma se i programmatori non possono sfruttare alcun tipo di garanzie comportamentali deboli, eventuali ottimizzazioni verranno annullate.