tags:

views:

261

answers:

6

This program:

#include <iostream>
#include <cstdlib>
#include <string>

int main(int argc, const char *argv[])
{
   using ::std::cerr;
   using ::std::cout;
   using ::std::endl;

   if (argc < 2 || argc > 3) {
      cerr << "Usage: " << argv[0] << " [<count>] <message>\n";
      return 1;
   }
   unsigned long count = 10000;
   if (argc > 2) {
      char *endptr = 0;
      count = ::std::strtoul(argv[1], &endptr, 10);
      if ((argv[1][0] == '\0') || (*endptr != '\0')) {
         cerr << "Usage: " << argv[0] << " [<count>] <message>\n";
         return 1;
      }
   }
   const ::std::string msg((argc < 3) ? argv[1] : argv[2]);
   for (unsigned long i = 0; i < count; ++i) {
      cout << i << ": " << msg << '\n';
   }
   return 0;
}

when timed like so:

$ time ./joe 10000000 fred >/dev/null

real  0m15.410s
user  0m10.551s
sys   0m0.166s

takes 15.4 seconds of real time to execute. Replace the output line with this: cout << i << ": " << msg << endl; and you end up with something like this:

$ time ./joe 10000000 fred >/dev/null

real  0m39.115s
user  0m16.482s
sys   0m15.803s

As you can see, the time to run more than doubles, and the program goes from spending minimal time in the OS to spending nearly half of it's time in the OS.

Both versions of the program have identical output, and are guaranteed by the standard to have identical output on every platform.

Given this, why do people persist in using endl as a synonym for '\n'?

Edit: In case it isn't obvious, this question is intended to be a leading question and is here for instructional purposes. I know why the performance penalty exists.

A: 

The real question is, why did the compiler make such a dogs breakfast of compiling the endl version? If they're guaranteed to have the same semantics, then they should also have the same runtime.

Edit: obviously, I wasn't aware that endl flushed the stream... that's what you get for not looking it up.

Andrew McGregor
They are not guaranteed to have the same semantics.
anon
They, in fact, most definitely do not have the same semantics.
Omnifarious
Well, they could do, they are just not guaranteed to by the C++ Standard.
anon
@Neil Butterworth, the standard allows `::std::cout` to be unbuffered?
Omnifarious
No, but the standard does not specify what the effect of outputting '\n' is.
anon
@Neil Butterworth, Ahh. *laugh* I suppose there's precedent. The stdio library in C treats '\n' specially and auto-flushes when it's encountered. They call it 'line buffering'.
Omnifarious
On many unixes, `std::cout` and `stdout` are line buffered only when the output is connected to an interactive terminal and not (e.g.) when attached to a file or other devices.
Charles Bailey
+5  A: 

Not everyone cares so much about performance. For some applications, guaranteeing the stream is flushed is much more important.

Edit: Also, I find endl easier to type than '\n' :-)

anon
In almost no case where I see `endl` used does it actually matter if the stream is flushed right then and there. :-)
Omnifarious
Logging applications, network communications and databases come immediately to mind.
anon
People should be using `::std::cerr` or some other unbuffered stream for logging. I've never seen a serious network application or database that used iostreams for communication over the network or writing to the database.
Omnifarious
You are the first person to give an actual answer, though I disagree with it. :-)
Omnifarious
There are very few uses were performance and stream are required in the same application. In which case it is generally easier to be consistant and use std::endl (apart from example programs to demonstrate the difference). Do I really care if an application takes 15 or 30 seconds.
Martin York
Actually Martin, that's my point, if your using std::iostream, then u did'nt care so much about performance, and if you care about performance, you didn't care too much about portability, so there's really few cases when you care about both things, so u have to worry for using proper newline character instead of std::endl
erick2red
@erick2red, except '\n' isn't any less portable than endl. THere is no portability performance tradeoff in using it. IMHO, it's completely senseless to use endl. People almost never need to actually flush the stream when they use it, they just saw it in a book and do it that way now without thinking or understanding the difference.
Omnifarious
+4  A: 

Afaik, endl also flushes the stream, which may be the cause of the performance penalty.

Helper Method
You are right. std::endl flushes the output buffer, and "\n" does not.
Mark Byers
I know why the performance penalty exists. :-) My question is: Why is `::std::endl` still just "what's done" even though it has that performance penalty?
Omnifarious
Probably because most programmers like it when their user can see the output instead of forcing them to wait until the buffer fills up. Given the speed of real output devices, it never really matters.
Hans Passant
+12  A: 

I'm not certain. Inserting std::endl into the output stream is defined as being equivalent to inserting .widen('\n') and then calling flush() and yet many programmers persist in using std::endl even when there is no cause to flush, for example they go on to immediately output something else.

My assumption is that it comes from an incorrect belief that it is somehow a more portable because it doesn't explicitly use a specific newline character. This is incorrect as \n must always be mapped to the system's correct newline sequence for non-binary files by the stream library.

Charles Bailey
You know, you are the first person who gave an actual answer. :-) Asking leading questions gets you nowhere on this site. I need to find a better way of stating questions I intend to be instructional.
Omnifarious
I gave an actual answer too, as it happens. You may not agree with it, of course.
anon
@Neil Butterworth, Oh, alright. Yes, Charles is the second person to give an actual answer. :-) Yours is too.
Omnifarious
Also, strictly speaking my answer isn't completely assumption; it's an extraction from an incredibly small sample size of developers I've talked to about this. The extrapolation probably has a very shaky statisical validity.
Charles Bailey
Interest in this question has faded, and you definitely have the best answer, with actual real data to back it up. :-)
Omnifarious
+2  A: 

I tend to use endl with on stringstreams as it makes it easy to spot missing linebreaks.

josefx
+1  A: 

My guess is that instructional texts use std::endl with the belief that it's simpler and less confusing for beginners, and afterward people got accustomed to using it.

jamesdlin