W niektórych przypadkach, takich jak opisany, Standard C ++ pozwala kompilatorom przetwarzać konstrukcje w sposób, który ich klienci uznaliby za najbardziej użyteczny, bez wymagania, aby takie zachowanie było przewidywalne. Innymi słowy, takie konstrukcje wywołują „Niezdefiniowane zachowanie”. Nie oznacza to jednak, że takie konstrukcje mają być „zabronione”, ponieważ Standard C ++ wyraźnie zrzeka się jurysdykcji w zakresie tego, co „dobrze” robią dobrze utworzone programy. Chociaż nie jestem świadomy żadnego opublikowanego dokumentu uzasadnienia standardu C ++, fakt, że opisuje on niezdefiniowane zachowanie podobnie jak C89, sugerowałoby, że zamierzone znaczenie jest podobne: „Niezdefiniowane zachowanie daje licencjodawcy implementację możliwość wychwytywania pewnych błędów programu, które są trudne zdiagnozować.
Istnieje wiele sytuacji, w których najskuteczniejszym sposobem przetworzenia czegoś jest zapisanie części struktury, o które będzie dbał dalszy kod, a pominięcie tych, o które dalszy kod nie będzie dbał. Wymaganie, aby programy inicjalizowały wszystkich członków struktury, w tym tych, o które nigdy nie będzie się troszczyć, niepotrzebnie ograniczyłoby wydajność.
Ponadto istnieją sytuacje, w których najskuteczniejsze może być zachowanie niezainicjowanych danych w sposób niedeterministyczny. Na przykład biorąc pod uwagę:
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;
}
jeśli dalszy kod nie będzie dbał o wartości jakichkolwiek elementów x.dat
lub y.dat
których indeksów nie wymieniono arr
, kod można zoptymalizować w celu:
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;
}
}
Ta poprawa wydajności nie byłaby możliwa, gdyby programiści byli zobowiązani do jawnego napisania każdego elementu temp.dat
, w tym tych, którzy nie będą się przejmować, przed skopiowaniem.
Z drugiej strony istnieją pewne aplikacje, w których ważne jest uniknięcie możliwości wycieku danych. W takich aplikacjach przydatne może być posiadanie wersji kodu, która jest instrumentem służącym do przechwytywania wszelkich prób kopiowania niezainicjowanej pamięci, bez względu na to, czy dalszy kod będzie na nią patrzeć, lub przydatne może być posiadanie gwarancji wdrożenia, że dowolna pamięć których zawartość może być wyciekła, zostałaby wyzerowana lub w inny sposób nadpisana danymi niepoufnymi.
Z tego, co mogę powiedzieć, standard C ++ nie próbuje powiedzieć, że którekolwiek z tych zachowań jest na tyle bardziej przydatne niż inne, że uzasadnia to nakazanie. Jak na ironię ten brak specyfikacji może mieć na celu ułatwienie optymalizacji, ale jeśli programiści nie będą mogli wykorzystać słabych gwarancji behawioralnych, wszelkie optymalizacje zostaną zanegowane.