Welche Bedeutung hat das Einbeziehen?
ios_base::sync_with_stdio(false);
cin.tie(NULL);
in C ++ - Programmen?
In meinen Tests wird die Ausführungszeit verkürzt. Gibt es jedoch einen Testfall, über den ich mir Sorgen machen sollte, wenn ich diesen einbeziehe?
Müssen die beiden Aussagen immer zusammen sein, oder reicht die erste aus, dh ignoriert cin.tie(NULL)
?
Ist es auch zulässig, gleichzeitige C- und C ++ - Befehle zu verwenden, wenn der Wert auf festgelegt wurde false
?
https://www.codechef.com/viewsolution/7316085
Der obige Code funktionierte einwandfrei, bis ich ihn scanf/printf
in einem C ++ - Programm mit dem Wert as verwendete true
. In diesem Fall gab es einen Segmentierungsfehler. Was könnte die mögliche Erklärung dafür sein?
Antworten:
Die beiden Aufrufe haben unterschiedliche Bedeutungen, die nichts mit der Leistung zu tun haben. Die Tatsache, dass es die Ausführungszeit beschleunigt, ist (oder könnte ) nur ein Nebeneffekt. Sie sollten verstehen, was jeder von ihnen tut, und sie nicht blind in jedes Programm aufnehmen, da sie wie eine Optimierung aussehen.
Dies deaktiviert die Synchronisation zwischen den C- und C ++ - Standardströmen. Standardmäßig sind alle Standard-Streams synchronisiert, sodass Sie in der Praxis E / A im C- und C ++ - Stil mischen und vernünftige und erwartete Ergebnisse erzielen können. Wenn Sie die Synchronisation deaktivieren, dürfen C ++ - Streams ihre eigenen unabhängigen Puffer haben, was das Mischen von E / A im C- und C ++ - Stil zu einem Abenteuer macht.
Beachten Sie auch, dass synchronisierte C ++ - Streams threadsicher sind (die Ausgabe von verschiedenen Threads kann sich verschachteln, Sie erhalten jedoch keine Datenrennen).
Dies löst sich
cin
voncout
. Gebundene Streams stellen sicher, dass ein Stream vor jeder E / A-Operation des anderen Streams automatisch gelöscht wird.Standardmäßig
cin
ist gebunden,cout
um eine sinnvolle Benutzerinteraktion zu gewährleisten. Beispielsweise:Wenn
cin
undcout
gebunden sind, können Sie erwarten, dass die Ausgabe gelöscht wird (dh auf der Konsole sichtbar ist), bevor das Programm Eingaben vom Benutzer auffordert. Wenn Sie die Streams lösen, blockiert das Programm möglicherweise das Warten auf die Eingabe des Namens durch den Benutzer, aber die Meldung "Name eingeben" ist noch nicht sichtbar (da diecout
Ausgabe standardmäßig gepuffert ist, wird sie nur bei Bedarf oder wenn die Ausgabe auf der Konsole gelöscht / angezeigt Puffer ist voll).Also , wenn Sie untie
cin
auscout
, müssen Sie sicherstellen, spülencout
manuell jedes Mal , wenn Sie angezeigt werden, bevor sie auf erwartete Eingabe etwas wollencin
.Wissen Sie abschließend, was jeder von ihnen tut, verstehen Sie die Konsequenzen und entscheiden Sie dann, ob Sie den möglichen Nebeneffekt einer Geschwindigkeitsverbesserung wirklich wollen oder brauchen .
quelle
cout
wird aus einem bestimmten Grund gepuffert. Wenn Sie es zu oft spülen und es nicht wirklich benötigen, wird möglicherweise ein Leistungseinbruch angezeigt.scanf()
leeren, die Pufferung vollständig deaktivieren oder zur Zeilenpufferung wechseln (die nach dem Zeilenumbruch oder beim Lesen der Eingabe gelöscht werden solltestdin
- siehe linux.die.net/man/3/setlinebuf ).Dies dient zum Synchronisieren von E / A aus der C- und C ++ - Welt. Wenn Sie synchronisieren, haben Sie die Garantie, dass die Reihenfolge aller E / A genau Ihren Erwartungen entspricht. Im Allgemeinen ist das Problem die Pufferung von E / A, die das Problem verursacht. Durch die Synchronisierung können beide Welten dieselben Puffer gemeinsam nutzen. Zum Beispiel
cout << "Hello"; printf("World"); cout << "Ciao";
; Ohne Synchronisation werden Sie nie wissen, ob SieHelloCiaoWorld
oderHelloWorldCiao
oderWorldHelloCiao
...tie
können Sie die Garantie , dass IOs Kanäle in C ++ Welt sind gebunden zu einander, das heißt zum Beispiel , dass jeder Ausgang vor Eingänge (man denke etwa auftritt gespült wurdencout << "What's your name ?"; cin >> name;
).Sie können jederzeit C- oder C ++ - E / A-Vorgänge mischen. Wenn Sie jedoch ein angemessenes Verhalten wünschen, müssen Sie beide Welten synchronisieren. Beachten Sie, dass es im Allgemeinen nicht empfohlen wird, sie zu mischen, wenn Sie in C C stdio programmieren und wenn Sie in C ++ programmieren, Streams verwenden. Möglicherweise möchten Sie jedoch vorhandene C-Bibliotheken in C ++ - Code mischen. In diesem Fall müssen beide synchronisiert werden.
quelle
cout <<
die Reihenfolge nicht ändern, sodassCiaoHelloWorld
dies für Ihren Beispielfall nicht möglich ist. Bei der Synchronisation geht es ausschließlich um verschiedene Puffermethoden.Die Verwendung
ios_base::sync_with_stdio(false);
reicht aus, um dieC
undC++
Streams zu entkoppeln . Eine Diskussion hierzu finden Sie in Standard C ++ IOStreams and Locales von Langer und Kreft. Sie stellen fest, dass die Funktionsweise der Implementierung definiert ist.Der
cin.tie(NULL)
Aufruf scheint eine Entkopplung zwischen den Aktivitäten aufcin
und anzuforderncout
. Ich kann nicht erklären, warum die Verwendung dieser Option mit der anderen Optimierung zu einem Absturz führen sollte. Wie bereits erwähnt, ist der von Ihnen angegebene Link schlecht, daher hier keine Spekulationen.quelle
Es ist nur üblich, dass Cin- Eingaben schneller funktionieren.
Für eine kurze Erklärung: In der ersten Zeile wird die Puffersynchronisation zwischen dem Cin- Stream und den C-Style- Stdio- Tools (wie ScanF oder Gets) deaktiviert. Cin funktioniert also schneller, aber Sie können es nicht gleichzeitig mit Stdio- Tools verwenden.
In der zweiten Zeile wird cin von cout getrennt. Standardmäßig wird der cout- Puffer jedes Mal geleert, wenn Sie etwas von cin lesen . Und das kann langsam sein, wenn Sie wiederholt etwas Kleines lesen und dann mehrmals etwas Kleines schreiben. Die Zeile schaltet diese Synchronisation aus (indem cin buchstäblich mit null anstelle von cout verknüpft wird ).
quelle