2014-09-05 3 views
18

Beachten Sie Folgendes:Ist es zulässig, einen `std :: ostream` aus einem Nullpuffer zu konstruieren?

std::ostream out(nullptr); 

diese legal ist und gut definiert?


Wie wäre es, wenn ich jetzt tun:

out << "hello world\n"; 

Ist das legal und gut definiert? Wenn ja, ist es vermutlich ein No-Op der Sorte?

+0

ich immer ein Unit-Test hinzufügen, wenn ich so etwas denken sollte funktionieren, und scheint gültig zu sein. Auf diese Weise, wenn jemand für einen anderen Compiler/Plattform stdlib erstellt, dann wissen sie, dass es kaputt ist. – paulm

+2

@paulm: Ich stimme fast zu, außer Unit Tests sind nicht etwas, auf das Sie sich verlassen sollten, um die Definiertheit zu validieren. –

+0

Wenn nicht auf Speicher außerhalb der Grenzen oder etwas zugegriffen wird, sehe ich kein Problem? Aber dann sollten Unit Tests mit App Verifier aktiviert sein/Valgrind usw. – paulm

Antwort

22

Ja, es ist legal und gut definiert, diesen Stream zu instanziieren. Sie können es sicher mit einem anderen Stream austauschen oder ihm zu einem späteren Zeitpunkt einen neuen Zeiger (dieses Mal auf einen vorhandenen Puffer) geben. Die Ausgabeoperation selbst ist in der Tat ein No-Op.

Hier ist der Grund:

  1. Die Konstruktion keine nicht-null Voraussetzung hat, und hat nur diese Nachbedingung:

    [C++11: 27.7.3.2/2]: Nachbedingung: rdbuf() == sb.

  2. Interessanterweise macht es einen expliziten Punkt, dass keine Operation wird auf sb im Konstruktor durchgeführt werden:

    [C++11: 27.7.3.2/4]: Bemerkungen: Führt keine Operationen auf rdbuf(). auch

  3. Aber Achtung:

    [C++11: 27.7.3.2/1]: Effekte: Konstruiert ein Objekt der Klasse basic_ostream, Anfangswerte an die Basisklasse Zuweisung durch den Aufruf basic_ios<charT,traits>::init(sb) (27.5.5.2).

  4. Das init(sb) Aufruf hat die Wirkung der badbit auf den Strom eingestellt wird, wenn sb NULL ist:

    [C++11: 27.5.5.2/3]: Nachbedingungen: Die Nachbedingungen dieser Funktion sind in der Tabelle angegeben 128.

    [C++11: Table 128]:[..]rdstate(): goodbit wenn sb kein Nullzeiger ist, sonst badbit. [..]

  5. die Ausgabeoperation würde Ergebnis in Handlungen entspricht dereferenzieren einen Nullzeiger:

    [C++11: 27.7.3.1/2]: Zwei Gruppen von Mitgliedsfunktionssignaturen teilen gemeinsame Eigenschaften: Die formatierten Ausgabefunktionen (oder Kuvertiermaschinen) und die unformatierten Ausgabefunktionen. Beide Gruppen von Ausgabefunktionen erzeugen (oder fügen) Ausgabezeichen durch Aktionen ein, die dem Aufruf rdbuf()->sputc(int_type) entsprechen. Sie dürfen andere öffentliche Mitglieder von basic_ostream verwenden, außer dass sie keine virtuellen Mitglieder von rdbuf() mit Ausnahme von overflow(), xsputn() und sync() aufrufen dürfen.

    außer es nie so weit, denn für basic_ostream::sentry Bau bekommt:

    [C++11: 27.7.3.4/3]: Wenn nach jeder Vorbereitung abgeschlossen ist, os.good()true ist, ok_ == true sonst ok_ == false.

    und für explicit operator basic_ostream::sentry::bool() const;:

    [C++11: 27.7.3.4/5]: Effekte: Gibt ok_.

    und:

    [C++11: 27.7.3.7/1]: Jede unformatierte Ausgangsfunktion beginnt die Ausführung durch ein Objekt der Klasse sentry zu konstruieren. Wenn dieses Objekt true zurückgibt, versucht die Funktion beim Konvertieren in einen Wert vom Typ bool die angeforderte Ausgabe zu generieren. [..]

    & hellip; die Implikation, dass keine Ausgabeoperation überhaupt stattfindet, wenn badbit bereits gesetzt ist.

This was also the case in C++03.

+1

+1 Coole Sache! Gut zu wissen, wie man mit 'std :: ostream' effektiv ein '/ dev/null 'erstellt. –

Verwandte Themen