2016-08-23 5 views
43

Im Buch Effective C++, sah ich die Passage unter:Welche Funktion schreibt C++ und ruft eine leere Klasse auf?

Als Ergebnis, wenn Sie

class Empty{}; 

es ist im Wesentlichen das gleiche schreiben, als ob Sie das geschrieben hatte:

Der folgende Code bewirkt, dass jede Funktion generiert wird:

Aber nach dem Zerlegen der ausführbaren Datei, die durch das Kompilieren des obigen Codes erstellt wurde, erkannte ich, dass es nicht der Fall ist: Es wird keine Funktion aufgerufen.

Hier ist das Haupt Assembler-Code:

00000000004006cd <main>: 
    4006cd:  55      push %rbp 
    4006ce:  48 89 e5    mov %rsp,%rbp 
    4006d1:  b8 00 00 00 00   mov $0x0,%eax 
    4006d6:  5d      pop %rbp 
    4006d7:  c3      retq 

Es gibt keine Funktion "Empty" im .text Segment genannt.

Was ist dann das Verhalten eines Compilers, nachdem wir einen Konstruktor oder eine Zuweisung einer leeren Klasse aufgerufen haben? Erzeugt es einige Funktionen, wie das Buch sagt? Wenn ja, wo werden sie gespeichert?

+12

Haben Sie mit Optimierungen kompiliert? – Rakete1111

+8

Um pedantisch zu sein, ist 'Empty() {...}' nicht ganz * äquivalent zu dem, was der Compiler erzeugt, um das gleiche zu erhalten, was der Compiler erzeugt, müßte man 'Empty() = default;'. Es gibt feine Unterschiede - das gleiche gilt für die anderen Mitglieder. Sehen Sie hier: http://en.cppreference.com/w/cpp/language/default_constructor#Trivial_default_constructor –

+0

ohne irgendwelche Optimierungen – linvoker

Antwort

54

Die Funktionen existieren, können aber inlined sein.

Wenn der Compiler die Funktionen einleitet, erkennt er, dass es sich um No-Ops handelt, und es wird kein Code generiert.

Was das Buch sagt, ist bis zu einem gewissen Grad wahr, die fiktiven Funktionen werden vom Compiler für Inline- und Direktaufrufe erstellt.

Der generierte Code ist jedoch leer, daher entfernt ein optimierender Compiler alle Hinweise auf die Funktion (richtet einen this-Zeiger ein), und die Funktionen werden niemals direkt aufgerufen.

Das Buch versucht nicht wirklich, den generierten Code zu erklären, sondern den Einfluss des Erstellens einer Klasse und die "versteckten" Funktionen, die für den normalen Betrieb generiert werden.

+17

Auch möchten Sie vielleicht lesen über [als-ob Regel] (http://stackoverflow.com/questions/15718262/what-exactly-is-the-as-if-rule) – MatthewRock

21

Diese Methoden werden zwar für die Klasse generiert, aber sie werden als "Inline" generiert.

Da es sich um Member-by-Member-Implementierungen handelt (z. B. kopiert der Kopierkonstruktor alle Member), wenn class leer ist, wird in ihnen nichts getan, und inline sind sie nur unsichtbar.

Es ist sehr wichtig, jedoch zu bedenken, dass diese Methoden ... zum Beispiel automatisch eine Implementierung bekommen Sie den Code

struct Foo { 
    char *buf; 
    Foo() : buf(new char[10]) {} 
    ~Foo() { delete[] buf; } 
}; 

Buggy ist, weil der automatisch generierten Code für Copykonstruktor und Zuordnung falsch und führt zu mehrfaches Löschen des Puffers

Es ist Buggy nicht wegen etwas, das geschrieben wurde, aber für etwas, das nicht geschrieben hat und das ist knifflig.Deshalb ist es äußerst wichtig, sich daran zu erinnern, was C++ automatisch für Sie schreibt: Wenn diese Implementierung das ist, was Sie wollen, dann perfekt, aber wenn nicht, dann reparieren Sie es, indem Sie die korrekte Implementierung bereitstellen oder die Erstellung oder Verwendung dieses falschen Codes verbieten.

9

Sie und das Buch kommen in dieser Situation aus verschiedenen Ebenen der Abstraktion.

Das Buch verwendet den Begriff "generated", um auf C++ - Funktionen zu verweisen, die implizit vom Compiler in das abstrakte C++ - Programm definiert werden. Das passiert absolut.

Sie interpretieren dies als tatsächliche Generierung des tatsächlichen Maschinencodes im übersetzten Programm. Das ist nicht was es bedeutet. Die Erzeugung des tatsächlichen Maschinencodes unterliegt immer den Launen des Compilers, solange die Semantik Ihres ursprünglichen abstrakten Programms beibehalten wird.

Als solches ist das Buch sicherlich nicht falsch, obwohl ich wahrscheinlich im Interesse der Klarheit ein anderes Wort verwendet hätte. Die Einhaltung der Standard-Terminologie tut nie weh.

+2

Dies ist meine Lieblingsantwort, weil es mehr ist Allgemeines. Inline-Funktionen oder nicht, der Compiler kann nichts ausgeben, weil das Programm nichts tut. Die Unterscheidung zwischen dem abstrakten C++ - Programm und der konkreten Maschinencode-Implementierung ist sehr wichtig. –

+0

@JordanMelo: Schön, dass es dir gefallen hat - genau das wollte ich! –

Verwandte Themen