2014-03-28 8 views
7

In 8.4.2 Explicitly-defaulted functions [dcl.fct.def.default] der Normeine Funktion deklarieren, wie nach der ersten Erklärung vorbelegt

Explizit ausgefallene Funktionen und implizit deklarierte Funktionen sind kollektiv notleidenden Funktionen genannt, und die Umsetzung wird für sie implizite Definitionen liefern (12.1 12.4, 12.8), die möglicherweise bedeuten, sie als gelöscht zu definieren. Eine spezielle Elementfunktion ist , die vom Benutzer bereitgestellt wird, wenn sie vom Benutzer deklariert und nicht explizit voreingestellt ist, oder wenn bei ihrer ersten Deklaration gelöscht wird. Eine vom Benutzer bereitgestellte explizit voreingestellte -Funktion (d. H. Explizit nach ihrer ersten Deklaration voreingestellt) ist definiert an dem Punkt, an dem sie explizit voreingestellt ist; Wenn eine solche Funktion implizit als gelöscht definiert ist, ist das Programm schlecht formatiert. [Anmerkung: eine Funktion als vorbelegt nach seiner ersten Erklärung Deklarieren kann eine effiziente Ausführung und knappe Definition liefern, während eine stabile binäre Schnittstelle zu einem base.-Endnote sich entwickelnden Code ermöglicht]

Was die Notiz tut am Ende gemein? Aus dem, was ich sehen kann, macht die Deklaration einer Funktion als Standard nach der ersten Deklaration die Funktion benutzerdefiniert, macht die Funktion also nicht-trivial und macht daher entweder den Typ nicht-trivialen Standardkonstruktor oder macht den Typ nicht-trivial -kopierbar, und machen Sie natürlich den Typ nicht-trivial und nicht-POD, während immer noch die Implementierung die tatsächliche Definition der Funktion zur Verfügung stellen. Aber ich verstehe nicht, wie dies zu "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base" führt. Alle Gedanken sind willkommen und reale Beispiele werden sehr geschätzt. Vielen Dank.

Ein Beispiel einer solchen Art:

struct A { 
    A(); 
}; 
A::A() = default; 
+0

Eine gute Frage, Sir. –

+2

Ich denke, was gemeint ist, ist gegeben, dass struct A {A(); }; A :: A() {} ', ändere es in' struct A {A() = default; }; 'ist eine brechende Änderung (bereits kompilierter Code, der die Klasse verwendet, muss neu kompiliert werden), ändert es jedoch in' struct A {A(); }; A :: A() = default; 'ist keine brechende Änderung. – hvd

+1

Ich stimme @hvd zu, der seine Antwort als Antwort geschrieben haben sollte, nicht als Kommentar. –

Antwort

6

Sie

// A.h 
struct A { 
    A(); 
}; 

und

// A.cc 
A::A() { } 

Sie können es auf

Angenommen haben ändern
// A.cc 
A::A() = default; 

um den Code nicht zu erzwingen, indem A.h neu kompiliert wird.

Für einen Standardkonstruktor macht dies nicht viel Sinn. = default nimmt mehr Zeichen als { }. Aber denken Sie an andere Konstruktortypen: Ein Copy- oder Move-Konstruktor kann viel kürzer werden, wenn es nicht mehr notwendig ist, jedes Feld explizit zu nennen, und abhängig vom Compiler und Typ, mit dem Sie es zu tun haben, kann der ausgefallene Copy/Move-Konstruktor sogar ausgeführt werden besser, zum Beispiel, wenn der Compiler nur erkennen kann, dass ein memcpy Aufruf ausreicht, wenn Sie die = default Syntax verwenden.

+1

+1: Ich denke, das ist es.Der Schlüssel ist, dass die Trivialität von vornherein für die Anwendung der Klausel verwirkt sein muss. –

+0

Vielen Dank für die Gedanken. Für den Fall von copy ctor, so sagen Sie, obwohl der Typ als nicht-trivial-kopierbar mit dieser "deferred = default definition" -Syntax gemacht wird, kann die Implementierung immer noch Dinge wie 'memcpy' tun, wenn sie es für angemessen hält? Dies scheint mit der Anforderung in '3.9 [basic.types] -Absätzen 3' zu kollidieren, die besagt, dass nur trivial kopierbare Typen Byte-weise Kopieräquivalenz garantieren. – goodbyeera

+0

@goodbyeera Wenn der Compiler weiß, dass 'memcpy' genau das tut, was der Standard beschreibt, darf der Compiler' memcpy' aufrufen. Nicht nur für Kopierkonstrukteure, sondern überall. – hvd

Verwandte Themen