Czy nadal można bezpiecznie usunąć nullptr w c ++ 0x?

84

W c++03nim jest całkiem jasne, że usuwając wskaźnik NULL nie ma żadnego wpływu. Rzeczywiście, jest wyraźnie stwierdzone, §5.3.5/2że:

W obu przypadkach, jeśli wartość operandu delete jest pustym wskaźnikiem, operacja nie ma żadnego efektu.

Jednak w obecnym projekcie dla c++0xtego zdania wydaje się być brakuje. W pozostałej części szkicu mogłem znaleźć tylko zdania stwierdzające, co się stanie, jeśli operand wyrażenia delete nie jest stałą zerowego wskaźnika. Czy usuwanie pustego wskaźnika jest nadal zdefiniowane w programie c++0x, a jeśli tak, to gdzie?

Uwagi:

Istnieją istotne poszlaki sugerujące, że jest on nadal dobrze zdefiniowany.

Po pierwsze, istnieją dwa zdania w §5.3.5/2stwierdzające, że

W pierwszej alternatywie (obiekt usuń) wartość argumentu usuwania może być wartością wskaźnika zerowego, ...

i

W drugiej alternatywie (tablica usuwania) wartość argumentu usuwania może być wartością wskaźnika zerowego lub ...

Mówi się, że operand może być zerowy, ale sam w sobie nie definiuje, co się stanie, jeśli tak jest.

Po drugie, zmiana znaczenia delete 0jest poważną i przełomową zmianą, a komitet normalizacyjny raczej nie wprowadziłby tej konkretnej zmiany. Ponadto nie ma wzmianki o tym, że jest to przełomowa zmiana w załączniku dotyczącym zgodności (załącznik C) do c++0xprojektu. Załącznik C jest jednak częścią informacyjną, więc nie ma to wpływu na interpretację normy.

Z drugiej strony fakt, że usunięcie wskaźnika zerowego jest wymagane, aby nie przyniosło żadnego efektu, oznacza dodatkowe sprawdzenie w czasie wykonywania. W wielu kodach operand nigdy nie może być zerowy, więc to sprawdzenie w czasie wykonywania jest sprzeczne z zasadą zerowego narzutu. Być może komisja po prostu zdecydowała się zmienić zachowanie, aby dostosować standard C ++ bardziej do założonych celów projektowych języka.

Mankarse
źródło

Odpowiedzi:

102

5.3.5 / 7 mówi:

Jeśli wartość operandu wyrażenia usuwającego nie jest wartością wskaźnika zerowego, wyrażenie usuwające wywoła funkcję cofnięcia alokacji (3.7.4.2). W przeciwnym razie nie jest określone, czy zostanie wywołana funkcja zwalniania.

A 3.7.4.2/3 mówi:

Wartość pierwszego argumentu dostarczonego do funkcji cofania alokacji może być pustą wartością wskaźnika; jeśli tak, i jeśli funkcja zwalniania alokacji jest podana w bibliotece standardowej, wywołanie nie ma żadnego efektu.

Tak więc zachowanie jest dobrze zdefiniowane, o ile używana jest standardowa funkcja zwalniania alokacji lub funkcja zwalniania dostarczona przez użytkownika poprawnie obsługuje wskaźniki zerowe.

interjay
źródło
9
Od C ++ 14 „Jeśli wyrażenie zwraca wartość wskaźnika zerowego, nie są wywoływane żadne destruktory, a funkcja cofania alokacji nie jest wywoływana”.
Wormer
2
@Wormer Myślę, że ta strona nie jest poprawna. Standard C ++ 14 nadal mówi, że „nie jest sprecyzowane, czy funkcja cofnięcia alokacji zostanie wywołana”, gdy wskaźnik ma wartość null (5.3.5 / 7).
interjay
1
Poza tym nie jest bezpieczne wywoływanie funkcji fclose () dla pustego wskaźnika pliku. W systemie Ubuntu (i być może w innych systemach operacyjnych) fclose (NULL) powoduje błąd segmentacji.
Gerry Beauregard,
7

Z drugiej strony fakt, że usunięcie wskaźnika zerowego jest wymagane, aby nie przyniosło żadnego efektu, oznacza dodatkowe sprawdzenie w czasie wykonywania.

Nowe sformułowanie nie usuwa tego sprawdzenia w czasie wykonywania dla pustego wskaźnika. Odwrotnie: wersja robocza standardu jest jeszcze bliższa stwierdzeniu, że implementacja musi wykonać test zerowego wskaźnika, aby była zgodna.

Warto również zauważyć: stary standard zaprzeczał sobie, mówiąc (5.3.5 / 2), że „jeśli wartością argumentu delete jest wskaźnik zerowy, operacja nie ma żadnego skutku”, ale później powiedział, że (5.3.5 / 7) „wyrażenie usuwające wywoła funkcję cofnięcia alokacji”. Wywołanie funkcji jest efektem. Dzieje się tak szczególnie dlatego, że wywoływana funkcja może być zastąpiona operator delete.

Nowe sformułowanie usuwa tę sprzeczność, wyraźnie pozostawiając implementacji, czy funkcja cofnięcia alokacji zostanie wywołana w przypadku usunięcia wskaźnika zerowego.

David Hammen
źródło