\n vs endl in cout
-
In disem (relativ alten) Artikel über \n vs endl gibt es am Ende einen interessanten Twist:
http://www.aristeia.com/Papers/C++ReportColumns/novdec95.pdf
"My guess is that cout is still buffered under many (if not most)
implementations, but the standard will be the standard, so in the fu-
ture, cout will not be buffered. Yet most of the places where I ob-
serve endl being used gratuitously, the destination stream is cout.
Under those conditions, the call to endl is still unnecessary (the
stream is already being flushed after each write), but it’s no longer
defeating the buffering system"ist das heute noch wahr? Wenn ja, dann könnten wir in diesem FOrum ein und für alle mal beshcließen, dass cout<<x<<endl; nicht böse ist.
-
Ein Zitat aus dem Standard (damals Draft) wäre nicht schlecht gewesen. Ich kann das nämlich nicht direkt nachvollziehen. Nur bei (w)cerr steht dabei, dass unitbuf ungleich 0 initialisiert wird.
-
endl ist immer Boese, weil cin zu cout getied ist. Flushen ist daher nie noetig
-
Mal sehen, ob das einen Unterschied macht.
EDIT Änderungen:
- steady_clock statt monotonic_clock für gültiges C++11
- aufwärmen, um Caching-Effekte zu vermeiden#include <iostream> #include <chrono> template <class Action> static std::chrono::steady_clock::duration measure_n_times(long long n, Action const &action) { auto start = std::chrono::steady_clock::now(); for (long long i = 0; i < n; ++i) { action(); } auto finish = std::chrono::steady_clock::now(); return (finish - start); } int main() { auto n = 10000; //aufwärmen measure_n_times(n, [] { std::cout << "Hello, world!\n"; std::cout << "Hello, world!" << std::endl; }); auto nl = measure_n_times(n, [] { std::cout << "Hello, world!\n"; }); std::cout.flush(); auto endl = measure_n_times(n, [] { std::cout << "Hello, world!" << std::endl; }); std::cerr << "nl: " << nl.count() << '\n'; std::cerr << "endl: " << endl.count() << '\n'; std::cerr << "nl/endl: " << (static_cast<double>(nl.count()) / static_cast<double>(endl.count())) << '\n'; std::cin.get(); }
Windows 7, Visual C++ 2013 schrieb:
nl: 57408000
endl: 56628000
nl/endl: 1.01377std::endl
ist auf diesem System anscheinend minimal schneller.
-
TyRoXx schrieb:
Windows 7, Visual C++ 2013 schrieb:
nl: 57408000
endl: 56628000
nl/endl: 1.01377std::endl
ist auf diesem System anscheinend minimal schneller.Vista, GCC 4.8.1
nl/endl: ~0.84Bei mir ist das ohne endl bisschen schneller und außerdem spart man sich ein bisschen Schreibarbeit.
-
Bei mir ist endl auch langsamer:
auto nl = measure_n_times(n, [] { std::cout << "Hello, world!\n"; }); std::cout.flush(); auto endl = measure_n_times(n, [] { std::cout << "Hello, world!" << std::endl; });
nl/endl: Schwankt zwischen 0.76 und 0.84
auto endl = measure_n_times(n, [] { std::cout << "Hello, world!" << std::endl; }); std::cout.flush(); auto nl = measure_n_times(n, [] { std::cout << "Hello, world!\n"; });
nl/endl: Durchgängig ~0.70
CPU: i7-3930k
OS: Win7 x64, unter WOW64
GCC: 4.7.1 (glaub ich)Btw., für C++11 "monotonic_clock" statt "steady_clock".
-
Mit GCC 4.6 auf einem Linux bekomme ich bei Ausgabe ins Terminal auch 84%.
Wenn die Standardausgabe stattdessen nach/dev/null
geht, ist das ungefähr zehn mal so schnell fürendl
und das Verhältnis sinkt auf 31%.Für GCC 4.6 muss man
monotonic_clock
nehmen, weil das da noch nicht umbenannt war.EDIT: Es ist also in der Praxis nicht egal was man verwendet. Für mich persönlich ist der Unterschied auf Linux so gravierend, dass ich nie
endl
benutzen würde, wo auch\n
ginge.
-
Also bei mir kommt es stark auf die Anzahl Zeichen an. Je mehr Zeichen, desto ausgeglichener ist es bei mir. Wenn ich mal bei 10.000 Zeichen bin, macht es praktisch kein Unterschied mehr.
#include <chrono> #include <fstream> #include <iostream> #include <string> using namespace std; class stopwatch { private: chrono::time_point<chrono::high_resolution_clock> last_; public: stopwatch() { start(); } void start() { last_ = chrono::high_resolution_clock::now(); } chrono::milliseconds::rep elapsed() const { auto t = chrono::high_resolution_clock::now(); return chrono::duration_cast<chrono::milliseconds>(t - last_).count(); } }; template <class Action> double measure_n_times(long long n, Action const &action) { stopwatch sw; sw.start(); for (long long i = 0; i < n; ++i) { action(); } return sw.elapsed(); } string random_string( size_t n ) { const char* const chars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; const size_t length = strlen( chars ); string str; str.resize( n ); for( size_t i=0; i!=n; ++i ) { str[i] = chars[ rand() % length ]; } return str; } int main() { srand( time(NULL) ); const auto min_length = 100; const auto max_length = 1000; const auto runs = 100000; for(auto anz_chars=min_length; anz_chars!=max_length; anz_chars+=min_length) { ofstream file( "test.txt" ); auto time = measure_n_times(runs, [&] { file << random_string(anz_chars) << endl; }); cout << time << " ms bei " << anz_chars << " Zeichen mit endl." << '\n'; } cout << '\n' << '\n'; for(auto anz_chars=min_length; anz_chars!=max_length; anz_chars+=min_length) { ofstream file( "test.txt" ); auto time = measure_n_times(runs, [&] { file << random_string(anz_chars) << '\n'; }); cout << time << " ms bei " << anz_chars << " Zeichen mit \\n." << '\n'; } cin.get(); }
-
Kellerautomat schrieb:
endl ist immer Boese, weil cin zu cout getied ist. Flushen ist daher nie noetig
die meisten meiner Programme besitzen kein einziges cin.
-
otze schrieb:
Kellerautomat schrieb:
endl ist immer Boese, weil cin zu cout getied ist. Flushen ist daher nie noetig
die meisten meiner Programme besitzen kein einziges cin.
Bin gerade am Flughafen, daher unter Windows, GCC 4.8 ergibt bei mir 74%.
-
tie und line-buffering ist abschaltbar, std::endl ist es nicht. Also pro '\n'!
-
otze schrieb:
ist das heute noch wahr? Wenn ja, dann könnten wir in diesem FOrum ein und für alle mal beshcließen, dass cout<<x<<endl; nicht böse ist.
lol