2015-01-04 10 views
20

Ich möchte den Anwender meiner Klasse verhindern, dass sie als eine automatische Variable, also schreibe ich Code wie folgt:Was ist der Unterschied zwischen "= Standard" Destruktor und leerer Destruktor?

class A { 
private: 
    ~A() = default; 
}; 

int main() { 
    A a; 
} 

Ich gehe davon aus, dass der Code nicht kompiliert werden, sondern g ++ kompiliert ohne Fehler .

Allerdings, wenn ich den Code zu ändern:

class A { 
private: 
    ~A(){} 
}; 

int main() { 
    A a; 
} 

Nun g ++ gibt den Fehler, dass ~A() privat ist, wie meine Erwartung.

Was ist der Unterschied zwischen einem "= Standard" Destruktor und einem leeren Destruktor?

+4

Welche Version von gcc? –

+1

Lesen z.B. [Dieser Destruktor-Verweis] (http://en.cppreference.com/w/cpp/language/destructor), der Unterschied besteht darin, dass ein vom Benutzer bereitgestellter Destruktor (auch wenn er leer ist) * nicht-trivial * ist und von der Referenz: "Objekte mit trivialen Destruktoren benötigen keinen Löschausdruck und können durch einfaches Entfernen ihres Speichers entsorgt werden." –

+8

In Ihrem Fall gibt es keinen Unterschied, sowohl [gcc4.9 als auch clang3.5 weigern sich zu kompilieren] (http://coliru.stacked-crooked.com/a/41976bc03bc12c79) Ihr erstes Beispiel. Es muss ein Fehler in Ihrer Version von gcc sein. – Praetorian

Antwort

23

Ihr erstes Beispiel sollte nicht kompilieren. Dies stellt einen Fehler im Compiler dar, den es kompiliert. Dieser Fehler wurde in gcc 4.9 und höher behoben.

Der Destruktor definiert mit = default ist Trivial in diesem Fall. Dies kann mit std::is_trivially_destructible<A>::value erkannt werden.

aktualisieren

C++ 11 (und C++ 14) fest, dass, wenn man hat einen benutzer erklärt destructor (und wenn Sie nicht haben, entweder vom Benutzer erklärt bewegen spezielles Element) , dann tritt die implizite Generierung des Kopierkonstruktors und des Kopierzuweisungsoperators immer noch auf, aber dieses Verhalten ist veraltet. Das heißt, wenn Sie sich darauf verlassen, gibt Ihr Compiler möglicherweise eine Verwarnungswarnung (oder möglicherweise nicht). Beide

:

~A() = default; 

und:

~A() {}; 

sind benutzer erklärt, und so haben sie keinen Unterschied in Bezug auf diesen Punkt. Wenn Sie eines dieser Formulare verwenden (und keine Move-Member deklarieren), sollten Sie Ihre Copy-Member explizit als Standard angeben, explizit löschen oder explizit angeben, damit Sie nicht auf veraltetes Verhalten angewiesen sind.

Wenn Sie move members (mit oder ohne Deklaration eines Destruktors) deklarieren, werden die kopierten Elemente implizit gelöscht.

+2

@delphifirst: Compiler Bugs sind heutzutage sehr verbreitet. Als ich ein Student war, in den frühen 1980er Jahren, haben wir gelernt, dass jedes nichtgute Verhalten ein Fehler in unserem Code war, nicht im Compiler. Heute mache ich regelmäßig Compiler zum Absturz (ICE, Interner Compiler-Fehler), und dann ist es keine Frage, wessen Fehler es ist ... –

+0

@HowardHinnant: Ich vermisse einige Diskussion über ausgefallene versus nicht deklariert. Ich denke, das würde sich auf die Verwendung des Ausdrucks "Benutzer erklärt" durch den Standard beziehen, z. in C++ 11 §12.8/18. Bitte? –

+0

@ Cheersandthth.-Alf: Froh, zu helfen, aber ich verstehe deine Frage nicht. Wenn Sie fragen, ob ein spezielles Mitglied mit dem Status "= Standard" vom Benutzer deklariert wurde, lautet die Antwort ja, aber nicht vom Benutzer bereitgestellt. –