Создание нового объекта класса C с оператором new () выдает здесь ошибку:
class C
{
public:
C() {}
virtual ~C() {}
void operator delete(void*) = delete;
};
int main()
{
C* c = new C;
}
с C2280: 'void C::operator delete(void *)': function was explicitly deleted
Но когда я заменяю C() {}
с C() = default;
или удалить строку , так что компилятор вставляет конструктор по умолчанию (который я считаю , имеет тот же эффект с = default
), код будет компиляция и запуск.
Каковы различия между созданным компилятором конструктором по умолчанию и определяемым пользователем конструктором по умолчанию, которые делают это возможным?
Я получил некоторую подсказку в этой публикации , но класс C здесь (без предоставленного пользователем конструктора) не тривиален, так как деструктор является виртуальным, верно?
Скомпилировано с последней версией Visual Studio, c ++ 17.
noexcept
operator delete()
того, написан ли конструктор вручную или неявно сгенерирован. Что согласуется с моими ожиданиями - поскольку выражение может вызывать исключениеnew
, компилятору необходим доступoperator delete()
.noexcept
сделает компиляцию кода, но как ...?noexcept
как упомянул SebastianRedl, вызовoperator delete
не должен быть включен. Также g ++ только жалуется, если деструктор является виртуальным. В противном случае он всегда компилируется, даже если конструктор выбрасывает.Ответы:
new
Выражение вызывает соответствующийoperator new
и затем вызывает конструктор. Если конструктор выдаетnew
выражение исключения, необходимо отменить эффектoperator new
(чтобы избежать утечки памяти) путем вызова соответствующегоoperator delete
. Если последнее удалено,new
выражение не может вызвать его, что приводит к компиляторуerror: use of deleted function 'static void C::operator delete(void*)'
.noexcept
Конструктор не может выбросить исключение, следовательно, соответствующееoperator delete
не является необходимым , поскольку это не будет вызываться с помощьюnew
выражения.default
Конструктор тривиального класса такжеnoexcept
конструктор. Присутствие виртуального деструктора требует,operator delete
чтобы его не удаляли, потому что вызывается специальный скалярный деструктор удаления (деталь реализации, обеспечивающаяdelete
выражение через указатель базового класса)operator delete
.Кажется, стандарт C ++ не указывает, должен ли компилятор требовать,
operator delete
чтобы его не удаляли, даже если он не может быть вызванnew
выражением.gcc
однако, похоже, что он вообще не вызывает соответствующее выражениеoperator delete
вnew
выраженииdelete
d (опубликовал отчет об ошибке ).источник