В стандарте сказано ([expr.delete] / 5):
Если удаляемый объект имеет неполный тип класса на момент удаления, а полный класс имеет нетривиальный деструктор или функцию освобождения, поведение не определено.
Итак, если T
имеет нетривиальный деструктор или имеет operator delete
перегрузку, вы получите UB. Ничего не сказано о том, что UB основан на значении указателя (то есть, является ли он нулевым указателем или нет).
Что значит "объект удаляется"?
Можно подумать, что «объект удаляется» означает, что это предложение применяется только к delete
вызовам реальных объектов. И поэтому, если вы передадите нулевой указатель, он не применяется.
Во-первых, остальная часть стандартного обсуждения поведения delete
явно указывает на то, что его поведение не применяется к нулевым указателям. [expr.delete] / 6 и 7 оба начинаются с «Если значение операнда выражения удаления не является значением нулевого указателя». Пункт 5 явно не содержит этих слов. Следовательно, мы должны предположить, что это применимо к нулевым указателям.
Во-вторых, что означало бы «удаляемый объект», если бы ему был передан нулевой указатель? Ведь там нет никакого «объекта».
Хорошо, подумайте, что значит интерпретировать этот текст, если «объект удаляется» конкретно говорит об объекте в конце этого указателя. Что произойдет, если вы удалите массив неполных классов с помощью нетривиальных деструкторов?
По этой логике это предложение не применяется вне зависимости от того, является ли указатель нулевым или нет. Почему? Поскольку «удаляемый объект» относится к типу массив, а не к типу класса. Следовательно, этот пункт не может применяться. Это означает, что компилятор должен иметь возможность вызывать delete[]
для массива неполных классов.
Но это невозможно реализовать; это потребует от компилятора возможности отслеживать код, который еще не существует.
Таким образом, либо «удаляемый объект» предназначен для ссылки на std::remove_pointer_t<std::decay_t<decltype(expr)>>
, либо стандарт требует поведения, которое невозможно реализовать. Стандартную формулировку, вероятно, можно было бы немного очистить, заменив «Если удаляемый объект имеет неполный тип класса в момент удаления» на «Если T
является указателем на U
или массив U
, а U
имеет неполный тип класса в точка удаления, ... "
person
Nicol Bolas
schedule
17.11.2017
c
всегда будет NULL, тогда вам вообще не нужна строка с удалением, либо вы в конечном итоге разрешите присвоить ей какое-то значение позже, и в этом случае вам нужно полное определение типа ... - person lukas   schedule 17.11.2017C *c = nullptr; delete c;
в любом случае не должно быть, потому что он ничего не делает, и компилятор действительно сможет это обнаружить и оптимизировать. Но такой код указывает на то, что с вашим кодом что-то не так, реализовывать этот частный случай в компиляторе не стоит. - person t.niese   schedule 17.11.2017language-lower
, но в любом случае это законный вопрос, поскольку в этом случае стандарт может быть неоднозначным. Ноуп с одной стороны, УБ с другой. - person Slava   schedule 17.11.2017delete nullptr;
напрямую? - person iBug   schedule 17.11.2017nullptr
имеет другой тип - person Slava   schedule 17.11.2017delete c
типC
со значениемnullptr
. Вdelete nullptr
значениеnullptr
с типомnullptr_t
. - person Severin Pappadeux   schedule 17.11.2017