Was ist der <iosfwd> -Header?

Antworten:

71

Auf diese Weise können Sie in Ihren eigenen Headern Methoden deklarieren, die auf den Deklarationen von iostream-Typen #includebasieren, ohne die iostream-Header selbst verwenden zu müssen, die groß, komplex und langsam zu kompilieren sind.

Hier ist ein einfaches Beispiel:

// foo.h
#include <iosfwd>

void sucker(std::iostream& is);

 

// foo.cc
#include <iostream>

void sucker(std::iostream& is) {
    is >> somevar;
}
Marcelo Cantos
quelle
Können Sie im Detail erklären, wie Referenzen weitergeleitet werden?
wp2
2
@ wp2: Es deklariert nur die Typen, ohne sie zu definieren. Warum nicht selbst einen Blick hinein werfen? Es ist ziemlich klein.
Marcelo Cantos
1
Was ist der Vorteil von #include <iostream>foo.cc, anstatt es direkt in foo.h zu tun?
wp2
11
@ wp2: Ja, aber nur in der CPP-Datei, für die die Deklaration erforderlich ist, und nicht in jeder einzelnen CPP-Datei, die foo.h verwendet.
Marcelo Cantos
Hat iosfwd alles andere als jenseits des Namespace std {class istream; Cass ostream; }?
zzz777
39

Wie @Marcelo Cantos erwähnt hat, können Sie die Deklaration von iostream-Klassen und -Funktionen einschließen, ohne die vollständigen Definitionen einzuschließen . In C und C ++ ist eine Deklaration eine Aussage, die besagt: "Hier ist der Name von etwas (eine Funktion / Klasse / etc.), Aber ich werde Ihnen außer dem Namen nichts mehr darüber erzählen." Für eine Funktion bedeutet dies den Namen der Funktion, nicht jedoch den Textkörper, der den Funktionscode enthält. Für eine Klasse bedeutet dies den Namen der Klasse, jedoch keine der Mitgliedsvariablen oder -methoden der Klasse.

Umgekehrt ist eine Definition die vollständige Definition: der Funktionskörper, die Klassenmitglieder usw.

Oft benötigen Sie nur die Deklaration von etwas, das verwendet werden soll. Bei einer Funktion müssen Sie nicht wissen, wie der Funktionskörper aussieht, um ihn aufzurufen (außer bei Vorlagen- oder Inline-Funktionen). Ebenso müssen Sie bei einer Klasse nicht wissen, welche Mitglieder die Klasse hat, wenn Sie nur Zeiger oder Verweise auf Instanzen dieser Klasse weitergeben. Sobald Sie jedoch auf eine Mitgliedsvariable zugreifen oder eine Klassenmethode aufrufen müssen, benötigen Sie die vollständige Definition.

Indem nur die Deklarationen anstelle der Definitionen einbezogen werden, muss der Compiler insgesamt viel, viel weniger Code verarbeiten, und die Kompilierung erfolgt daher viel schneller.

Um Ihnen eine Vorstellung davon zu geben, wie viel Code verarbeitet wird, ist hier, wie viel Code in meiner lokalen Implementierung enthalten ist:

# The following commands create a source file that includes a single header
# file (on stdout), preprocess it with g++ -E, and then count how many lines
# are in the resulting preprocessed output
$ echo '#include <iosfwd>' | g++ -E -xc++ - | wc
    2598    6534   57875
$ echo '#include <iostream>' | g++ -E -xc++ - | wc
   25631   59613  631998

Eine Datei, die enthält <iosfwd>, muss der Compiler 2598 Codezeilen aus verschiedenen Header-Dateien verarbeiten, während eine Datei, die enthält <iostream>, satte 25631 Codezeilen verarbeiten muss. Das ist, bevor Sie den eigentlichen Code kompilieren, den Sie in Ihrer Quelldatei interessieren!

Adam Rosenfield
quelle
Wie der folgende Befehl funktioniert, $ echo '#include <iosfwd>' | g ++ -E -xc ++ - | wc Ich habe versucht, den folgenden Befehl auszuführen, aber er zeigt einen Fehler $ echo '#include <QtGlobal>' | g ++ -E -xc ++ - | wc Wo habe ich mich geirrt?
Beparas
14

Grundsätzlich gilt, wenn Sie verwenden, <iosfwd>weil Sie Abhängigkeiten zur Kompilierungszeit beseitigen möchten.

Sie verwenden <iosfwd>anstelle der herkömmlichen Stream-Header ( <iostream>und Freunde), um zu vermeiden, dass die Definition des gesamten Streaming-Materials eingeschlossen wird. Mit machen <iosfwd>Sie nur eine Vorwärtserklärung aller Streaming-Sachen.

Ich fand diesen Link besonders nützlich: http://www.gotw.ca/gotw/007.htm

Lesswire
quelle
3
Inwiefern ist dies aufschlussreicher als die beiden bereits existierenden und über 2 Jahre alten Antworten.
Christian Rau
Ich hatte den Eindruck, dass dies eher eine Build-Optimierung ist: Das Kompilieren dauert viel weniger <iosfwd>als <iostream>. Oder ist diese Anwendung der Hauptschwerpunkt dessen, was Sie gesagt haben?
@ChristianRau, Um Ihnen und Googlern bei der Antwort zu helfen: Zum einen (unter anscheinend mindestens einem Dutzend anderen) habe ich die Kürze dieses einen wirklich geschätzt. Ich brauchte nichts von den Flusen der anderen, nur das Zauberwort "Vorwärtsdeklaration" , das, wie Sie wahrscheinlich übersehen haben, nirgendwo anders auf dieser Seite auftauchte (außer dem Frage-Tag, das nach dieser Antwort hinzugefügt wurde ).
Gr.