Рассмотрим простую программу:
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:
В связанном коде есть ошибка, она сравнивает указатели, а не точные значения. Исправлены следующие результаты:
- без
ifguard:17.6 [s]40.8 [s], - с
ifguard:10.6 [s]31.5 [s], - с
ifзащитой и пользовательскимswap:10.4 [s]31.3 [s].
Эти результаты были абсолютно согласованы во многих пробегах с минимальным отклонением. Разница в производительности между первыми двумя случаями значительна, и я бы не сказал, что это какой-то "чрезвычайно редкий угловой случай", такой как код.