Utworzenie nowego obiektu klasy C za pomocą operatora new () powoduje błąd:
class C
{
public:
C() {}
virtual ~C() {}
void operator delete(void*) = delete;
};
int main()
{
C* c = new C;
}
z C2280: 'void C::operator delete(void *)': function was explicitly deleted
Ale kiedy wymienić C() {}
z C() = default;
lub usunąć linię tak, że kompilator wstawia konstruktor domyślny (który moim zdaniem ma taki sam skutek = default
), kod zostanie skompilowany i uruchomić.
Jakie są różnice między domyślnym konstruktorem generowanym przez kompilator a domyślnym konstruktorem zdefiniowanym przez użytkownika?
Mam trochę wskazówek w tym poście , ale klasa C tutaj (bez konstruktora podanego przez użytkownika) nie jest trywialna, ponieważ destruktor jest wirtualny, prawda?
Skompilowany z najnowszym Visual Studio, c ++ 17.
c++
delete-operator
default-constructor
yeshjho
źródło
źródło
noexcept
operator delete()
tego, czy konstruktor jest zapisywany ręcznie, czy też niejawnie. Co jest zgodne z moimi oczekiwaniami - ponieważnew
wyrażenie może generować wyjątek , kompilator musi uzyskać dostępoperator delete()
.noexcept
spowoduje kompilację kodu, ale jak ...?noexcept
tak, jak wspominał SebastianRedl,operator delete
nie trzeba dołączać wywołania . Również g ++ narzeka, tylko jeśli destruktor jest wirtualny. W przeciwnym razie zawsze się kompiluje, nawet jeśli konstruktor rzuca.Odpowiedzi:
new
wyrażenie wywołuje odpowiedni,operator new
a następnie wywołuje konstruktor. Jeśli konstruktor zgłaszanew
wyrażenie wyjątku, należy cofnąć efektoperator new
(aby uniknąć wycieku pamięci) przez wywołanie odpowiedniegooperator delete
. Jeśli to ostatnie zostanie usunięte,new
wyrażenie nie może go wywołać, co powoduje kompilatorerror: use of deleted function 'static void C::operator delete(void*)'
.noexcept
Konstruktor nie może wyrzucić wyjątek, a tym samym odpowiednioperator delete
nie jest konieczne, gdyż nie będzie się przeznew
wyrażenia.default
Konstruktor trywialny klasy takżenoexcept
konstruktor. Obecność wirtualnego destruktora wymagaoperator delete
usunięcia, ponieważ wywoływany jest specjalny destruktor usuwający skalar (szczegół implementacji umożliwiającydelete
wyrażenie poprzez wskaźnik klasy bazowej)operator delete
.Wydaje się, że standard C ++ nie określa, czy kompilator musi wymagać
operator delete
usunięcia, nawet jeśli nie można go wywołać przeznew
wyrażenie.gcc
Jednak nie wydaje się być wywołując odpowiednioperator delete
wnew
ekspresji w ogóle czy jestdelete
d (napisali raport o błędzie ).źródło