The short and simple answer is that using std::endl
can and will slow output by a huge margin. In fact, I'm reasonably convinced that std::endl
is responsible for most of the notion that C++ iostreams are substantially slower than C-style I/O.
For example, consider a program like this:
#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stdio.h>
char fmt[] = "%s\n";
static const int count = 3000000;
static char const *const string = "This is a string.";
static std::string s = std::string(string) + "\n";
void show_time(void (*f)(), char const *caption) {
clock_t start = clock();
f();
clock_t ticks = clock()-start;
std::cerr << std::setw(30) << caption
<< ": "
<< (double)ticks/CLOCKS_PER_SEC << "\n";
}
void use_printf() {
for (int i=0; i<count; i++)
printf(fmt, string);
}
void use_puts() {
for (int i=0; i<count; i++)
puts(string);
}
void use_cout() {
for (int i=0; i<count; i++)
std::cout << string << "\n";
}
void use_cout_unsync() {
std::cout.sync_with_stdio(false);
for (int i=0; i<count; i++)
std::cout << string << "\n";
std::cout.sync_with_stdio(true);
}
void use_stringstream() {
std::stringstream temp;
for (int i=0; i<count; i++)
temp << string << "\n";
std::cout << temp.str();
}
void use_endl() {
for (int i=0; i<count; i++)
std::cout << string << std::endl;
}
void use_fill_n() {
std::fill_n(std::ostream_iterator<char const *>(std::cout, "\n"), count, string);
}
void use_write() {
for (int i = 0; i < count; i++)
std::cout.write(s.data(), s.size());
}
int main() {
show_time(use_printf, "Time using printf");
show_time(use_puts, "Time using puts");
show_time(use_cout, "Time using cout (synced)");
show_time(use_cout_unsync, "Time using cout (un-synced)");
show_time(use_stringstream, "Time using stringstream");
show_time(use_endl, "Time using endl");
show_time(use_fill_n, "Time using fill_n");
show_time(use_write, "Time using write");
return 0;
}
With standard output redirected to a file, this produces the following results:
Time using printf: 0.208539
Time using puts: 0.103065
Time using cout (synced): 0.241377
Time using cout (un-synced): 0.181853
Time using stringstream: 0.223617
Time using endl: 4.32881
Time using fill_n: 0.209951
Time using write: 0.102781
Using std::endl
slowed the program by a factor of about 20 in this case. If you wrote shorter strings, the slow-down could/would be even greater.
There are a few cases where you really and truly do want to flush a stream manually--but they honestly are pretty few and far between.
Most times a stream needs to be flushed (e.g., you print a prompt, then wait for some input) it'll happen automatically unless you've used things like std::tie
and/or std::sync_with_stdio
to prevent that.
That leaves only a tiny number of truly unusual situations where you have good reason to flush a stream manually. Such cases are rare enough that it's well worth using std::flush
when they happen, to make it apparent to the anybody reading the code that you're flushing the stream intentionally (and more often than not, probably also merits a comment about why this is one of the rare cases when flushing the stream really makes sense).