Das Erstellen eines neuen Objekts der Klasse C mit dem Operator new () führt hier zu einem Fehler:
class C
{
public:
C() {}
virtual ~C() {}
void operator delete(void*) = delete;
};
int main()
{
C* c = new C;
}
mit C2280: 'void C::operator delete(void *)': function was explicitly deleted
Aber wenn ich ersetzen C() {}
mit C() = default;
oder die Zeile entfernen , so dass Compiler einen Standardkonstruktor fügt (was ich glaube die gleiche Wirkung mit hat = default
), wird der Code kompiliert und ausgeführt.
Was sind die Unterschiede zwischen dem vom Compiler generierten Standardkonstruktor und dem benutzerdefinierten Standardkonstruktor, die dies ermöglichen?
Ich habe einen Hinweis in diesem Beitrag erhalten , aber Klasse C hier (ohne vom Benutzer bereitgestellten Konstruktor) ist nicht trivial, da der Destruktor virtuell ist, oder?
Kompiliert mit dem neuesten Visual Studio, c ++ 17.
quelle
noexcept
operator delete()
ob der Konstruktor manuell geschrieben oder implizit generiert wird. Dies entspricht meinen Erwartungen - da dernew
Ausdruck möglicherweise eine Ausnahme auslöst, muss der Compiler darauf zugreifenoperator delete()
.noexcept
wird der Code kompiliert, aber wie ...?noexcept
um SebastianRedl handelt, muss ein Aufruf vonoperator delete
nicht enthalten sein. Auch g ++ beschwert sich nur, wenn der Destruktor virtuell ist. Andernfalls wird immer kompiliert, auch wenn der Konstruktor wirft.Antworten:
new
Ausdruck ruft den entsprechenden aufoperator new
und ruft dann den Konstruktor auf. Wenn der Konstruktor einen Ausnahmeausdrucknew
auslöst, muss der Effekt vonoperator new
(um Speicherverluste zu vermeiden) durch Aufrufen des entsprechenden Ausdrucks rückgängig gemacht werdenoperator delete
. Wenn letzteres gelöscht wirdnew
, kann der Ausdruck ihn nicht aufrufen, was zum Compiler führterror: use of deleted function 'static void C::operator delete(void*)'
.Ein
noexcept
Konstruktor kann möglicherweise keine Ausnahme auslösen, daher ist die entsprechendeoperator delete
nicht erforderlich, da sie nicht von einemnew
Ausdruck aufgerufen wird . Eindefault
Konstruktor einer trivialen Klasse ist auch einnoexcept
Konstruktor. Das Vorhandensein eines virtuellen Destruktors mussoperator delete
nicht gelöscht werden, da der spezielle skalare Löschdestruktor (ein Implementierungsdetail zum Aktivieren desdelete
Ausdrucks über den Basisklassenzeiger) aufgerufen wirdoperator delete
.Der C ++ - Standard scheint nicht spezifiziert zu sein, ob der Compiler
operator delete
nicht gelöscht werden muss, auch wenn er möglicherweise nicht durchnew
Ausdruck aufgerufen werden kann.gcc
Jedoch scheint nicht zu dem entsprechenden zu Aufrufenoperator delete
innew
Ausdruck überhaupt , wenn esdelete
d (schrieb einen Bug - Report ).quelle