2017-12-07 9 views
0

In einem Programm, das ich wurde auf die folgende Art und Weise auf irgend einem verwendeten Alias ​​für Byte arbeiten:Warum ist basic_fstream <vorzeichenloses Zeichen> Größenordnung unter basic_fstream <char> unter Windows?

#include <fstream> 
#include <vector> 
using Byte = unsigned char; 

void write(const Byte* buffer, size_t size) { 
    std::basic_fstream<Byte> file("1gb_file", std::ios::in | std::ios::out); 
    file.write(buffer, size); 
    file.flush(); // To ensure the data is being written, to eliminate caching claims 
} 

int main(){ 
    auto GB = 1024u * 1024u * 1024u; 
    std::vector<Byte> zeros(GB, 0); 
    write(zeros.data(), zeros.size()); 
    return 0; 
} 

Die Zeit diese Funktion auf Byte == unsigned char auszuführen hat: 52.0245s auf meine neue SSD, MSVC-x64 auf Release Modus.

Auf der anderen Seite, wenn wir die Definition zu Byte == char ändern: 1.46725s. Das ist es.

Warum ist dieser Unterschied, und gibt es allgemeine gute Praktiken bei der Verwendung der Standardbibliothek, um solche Fallstricke zu vermeiden?

Hinweis (Bearbeitet wegen eines Fehlers): Unter Linux läuft der Code tatsächlich nicht, wenn er unsigned char (auf gcc und clang) gegeben wird, wie @SergeyA darauf hinwies. Die GCC-Version unter Windows funktioniert auch nicht, im Gegensatz zu dem, was ich vorher geschrieben habe.

+0

Warum mussten Sie die Frage so hart auf Ihre Leser richten? Ihre Motive oder Ihr Alias ​​sind uns egal. Ihre Frage scheint in sich abgeschlossen zu sein. Alles, was wir brauchen, sind zwei Codeschnipsel, Kompilierungsflags und Befehlszeilen mit Zeiten für beide. – SergeyA

+0

In Ordnung. Wird das beheben. – Michael

+1

@SergeyA - die Frage ist genau dort im Titel des OP - das erste, was Sie lesen. – MFisherKDX

Antwort

0

Ich werde hier in den sauren Apfel beißen und denke, dass es mit Locales zu tun hat. Basierend auf sehr begrenzten Informationen, die ich habe, sieht es aus wie in MSVC unsigned Char-Streams, um Gebietsschema-Konvertierungen durchzuführen, während normale Char Streams nicht tun und stattdessen nur Bulk-IO. (Siehe Hinweise zu http://en.cppreference.com/w/cpp/io/basic_ostream/write).

Interessanterweise funktioniert das gleiche Code-Snippet überhaupt nicht auf meiner Linux-Installation mit g ++ 5.4 (ziemlich alt, ich weiß). Schreiben schlägt fehl, weil ein internes Member in der Stream-Klasse nullptr ist (wer immer es interessiert, ist _M_codecvt) und badbit des Streams ist gesetzt.

+0

Ich kompilierte und lief auf meiner VM unter Linux (Ubuntu 16.04, sowohl bei clang als auch bei gcc), es funktionierte in etwa die gleiche Geschwindigkeit. Ich habe auch über Konvertierungen nachgedacht, als dieser Bug zum ersten Mal auftrat, aber ich weiß nicht, dass dies der Fall ist. Das Konvertieren eines Zeigers von 'unsigned char' nach' char' ist sehr billig und das Konvertieren jedes Wertes klingt wie eine wirklich dumme Implementierung. – Michael

+1

@Michael, ich denke, du verstehst die Umwandlung falsch.Es ist keine Umwandlung der Zeiger, es ist die Umwandlung von Zeichen! Durch das Konvertieren von Gebietsschemas kann eine (Folge von) Zeichen in ein anderes konvertiert werden. Ich bin zu 80% sicher, dass das hier passiert. Übrigens, ich vermute jetzt, dass Sie denken, dass Sie 'std :: fstream ' verwenden müssen, um Datenblobs von 'unsigned char' zu speichern. Das ist total ** nicht ** der Fall. – SergeyA

+0

Write versagt auch für mich mit 'Byte = unsigned char' mit Linux g ++ 7.2.0 – MFisherKDX

Verwandte Themen