Рассмотрим простую программу:
int main() {
int* ptr = nullptr;
delete ptr;
}
С GCC (7.2) в результирующей программе есть инструкция call
относительно operator delete
. С компиляторами Clang и Intel таких инструкций нет, удаление нулевого указателя полностью оптимизировано (-O2
во всех случаях). Вы можете протестировать здесь: https://godbolt.org/g/JmdoJi.
Интересно, может ли такая оптимизация быть включена в GCC? (Моя более широкая мотивация связана с проблемой пользовательского swap
vs std::swap
для подвижных типов, где удаление нулевых указателей может представлять собой штраф за производительность во втором случае, см. qaru.site/info/19211/... для получения более подробной информации.)
UPDATE
Чтобы прояснить мою мотивацию для вопроса: если я использую только delete ptr;
без if (ptr)
guard в операторе присваивания перемещения и деструкторе некоторого класса, то std::swap
с объектами этого класса выдает команды 3 call
с GCC. Это может быть значительным снижением производительности, например, при сортировке массива таких объектов.
Кроме того, я могу писать if (ptr) delete ptr;
всюду, но задаюсь вопросом, не может ли это быть и штрафом за производительность, поскольку выражение delete
должно также проверять ptr
. Но, здесь, я думаю, компиляторы будут генерировать только одну проверку.
Кроме того, мне очень нравится возможность вызова delete
без охраны, и для меня это было неожиданностью, что он может дать разные результаты (производительности).
UPDATE
Я просто сделал простой тест, а именно сортировку объектов, которые вызывают delete
в их операторе присваивания и деструкторе. Источник находится здесь: https://godbolt.org/g/7zGUvo
Время работы std::sort
, измеренное с помощью знака GCC 7.1 и -O2
на Xeon E2680v3:
В связанном коде есть ошибка, она сравнивает указатели, а не точные значения. Исправлены следующие результаты:
- без
if
guard:17.6 [s]40.8 [s], - с
if
guard:10.6 [s]31.5 [s], - с
if
защитой и пользовательскимswap
:10.4 [s]31.3 [s].
Эти результаты были абсолютно согласованы во многих пробегах с минимальным отклонением. Разница в производительности между первыми двумя случаями значительна, и я бы не сказал, что это какой-то "чрезвычайно редкий угловой случай", такой как код.