26

I have recently read an article which stated that using \n is preferable to using std::endl because endl also flushes the stream.
But when I looked for a bit more information on the topic I found a site which stated:

If you are in a situation where you have to avoid buffering, you can use std::endl instead of ‘\n’

Now here comes my question: In which situation is it preferable not to write to the buffer? Because I only saw advantages of that technique. Isn't it also safer to write to the buffer? Because it is smaller than a hard drive it will get overwritten faster than data that is stored on the HD (I am not sure if this is true).

Petr
  • 9,812
  • 1
  • 28
  • 52
TheJavaFan
  • 341
  • 3
  • 15
  • 1
    When using buffering, it's possible that you do some dialog asking the user for data (with a prompt), and the text isn't printed before you read from the keyboard. In case of some peripherals (eg.serial port), it could happen that you write to the buffer, and, when the program stops, the peripheral is closed too (and the data isn't sent. – jcoppens May 15 '15 at 18:08

5 Answers5

20

When buffering occurs you will have no guarantees that the data is immediately received before a flush occurs. Under particular circumstances you might experience wrong output ordering and/or loss of information/debug data, e.g.

int main() {
   
    std::cout << "This text is quite nice and might as well be buffered";
    raise(SIGSEGV); // Oh dear.. segmentation violation
    std::cout << std::endl;
}

Live Example

Output:

bash: line 7: 22235 Segmentation fault      (core dumped) ./a.out

the above will not print any text since the buffering prevented the right output to be displayed.

Now if you simply add a flushing std::endl at the end of the buffer this is what you get

int main() {
   
    std::cout << "This text is quite nice and might as well be buffered" << std::endl;
    raise(SIGSEGV); // Oh dear.. segmentation violation
    std::cout << std::endl;
}

Live Example

Output:

This text is quite nice and might as well be buffered
bash: line 7: 22444 Segmentation fault      (core dumped) ./a.out

This time the output is visible before the program termination.

Implications of this fact are manifold. Purely speculative: if the data were related to a server log, your app could have crashed before the actual logging.

Marco A.
  • 43,032
  • 26
  • 132
  • 246
11

It will be preferable in any situation in which you want the output to actually appear exactly when it was supposed to appear.

A simple example:

#include <iostream>
int main() {
    std::cout << "Please enter your name: " << std::endl;
    std::string name;
    std::cin >> name;
    ...
}

With buffering, no text will appear on screen before the user is expected to type his/her name, so the user will be confused. (Note that in fact it might be really difficult or impossible to get this example run with buffering fully enabled, as C++ might take special measures to flush std::cout before any input from std::cin, see Why do we need to tie std::cin and std::cout?. But this is just a theoretical example: in case the buffering is fully enabled, the user will not see the prompt.)

Such a situation can occur from time to time, though it might not be very often. Consider writing to a pipe to interact with another process. Or even if your program writes to log file and you personally look into the log file from time to time to see how it runs --- in case of buffering, you usually will not see the output that has been printed from program, but still stays in the buffer yet.

Another important situation to account for --- if your program severely crashes, the buffer contents might not end on the hard drive at all. (I expect the stream destructors to flush the buffer, but a crash can be so severe that no destructors will be called at all.)

Community
  • 1
  • 1
Petr
  • 9,812
  • 1
  • 28
  • 52
  • @Petr But do you think that writting to the buffer is safer then writting to the HD ? – TheJavaFan Apr 17 '15 at 14:13
  • @TheJavaFan, what do you mean by "safer" and why you think it should be? I see no reason why it might be safer. (I see now that you asked this in your question too, but I also do not quite get the last sentence of your question.) – Petr Apr 17 '15 at 14:18
  • @Petr I was just wondering if data gets faster overwritten in the buffer then it does on the HD – TheJavaFan Apr 17 '15 at 14:20
  • 1
    @TheJavaFan, I do not understand the word "overwritten". When the buffer is filled up, it is flushed (written) to disk or wherever the stream was directed. After this, the buffer is reused and the old data in it is indeed overwritten (though it is already on the disk), but I see no relation of this to safety and no analogy with HD, so I don't see how we can compare buffer and HD. – Petr Apr 17 '15 at 14:24
  • 2
    @TheJavaFan If you mean "will buffering make things faster" the answer is yes, that's the entire purpose of buffering. Anyway [any time output timing is important](http://stackoverflow.com/a/29701830/1938163) you should consider pros and cons. This is entirely application-specific. – Marco A. Apr 17 '15 at 14:27
  • @Petr ok now I understand it! Thank you for your answer – TheJavaFan Apr 17 '15 at 14:33
  • 8
    @Petr your example ignores the fact that `std::cin` and `std::cout` are tied, such that any input operation on `std::cin` will first cause the output buffer of `std::cout` to be flushed. See http://stackoverflow.com/questions/14052627/why-do-we-need-to-tie-cin-and-cout for example. – Andrew Apr 17 '15 at 14:35
  • 8
    Andrew's absolutely right - this answer needs updating. A better example of where flushing is useful is something like `for (int i = 0; i < 10; ++i) { std::cout << "\rplease wait " << i << " more seconds..." << std::flush; sleep(1); }`. – Tony Delroy Apr 17 '15 at 14:39
  • @Andrew, I have updated the answer, thanks. Though it already included the "With buffering" disclaimer, I did never say that it will work by default. – Petr Apr 17 '15 at 14:47
  • Isn't endl basically "\n" + flush? So it will definitely flush in any case – Niklas B. May 19 '15 at 06:40
  • @NiklasB. yes, my example is just to illustrate the concept, I do not say that it will work in a default C++ compiler. – Petr May 19 '15 at 08:12
10

It is preferable to flush the buffer if you need the target of your stream to receive the data before the stream is closed.

A real-life example would be an application log, written from a stream that's always open... You may want to look at this log while the program is still running.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
10

First, a bit of revisionist history.

In the old days, when everybody used stdio.h library to do I/O, text that was viewed interactively was typically line buffered (or even unbuffered), and text that was not was fully buffered. So, if you output '\n' to the stream, it would "always" do the Right Thing: lines users were looking at get flushed and seen immediately, and lines getting dumped to file get buffered for maximum performance.

Unfortunately, it isn't actually always the Right Thing; the runtime cannot always predict how users actually want to view the output of your program. One common trap is redirecting STDOUT -- people get used to running their program in a console and seeing the output (with its line-buffered behavior) in the console, and then for whatever reason (e.g. long running job) they decide to redirect STDOUT to a file, and are promptly surprised by the fact the output is no longer line-buffered.

I have seen weeks of supercomputer time wasted for this reason; the output was infrequent enough that the buffering prevented anyone from being able to tell how the job was progressing.

C++'s iostream library, however, was designed to make it easy to do the Right Thing here. Except when synchronizing with stdio, it doesn't do this funny "maybe line-buffered maybe fully-buffered" thing. It always uses full buffering (except when you do unbuffered stuff, of course), and if you want things flushed on newline, you do so explicitly.

So if you're dumping a bunch of formatted text to a file that people won't be looking at until it's done, you write \n for your line breaks.

But if you're writing text people might actually want to look at while you're writing it, you use std::endl for your line breaks, and it gets displayed immediately. And if you're writing several lines at once, you can even do better: use '\n' for the intermediate line breaks and std::endl for the final one (or '\n' and std::flush). Although in this setting performance usually doesn't matter so it's usually fine to just use std::endl for all of the line breaks.

  • 1
    Just a note: even in _line-buffered_ case, the output will not always appear _immediately_, it will only appear after the first new-line. If you are outputting everything into one line, the output will effectively be fully buffered. To have the output appear really _immediately_, you need to explicitly call `flush()` after each output. – Petr Apr 17 '15 at 14:38
5

I hope you've lost the link to that site that you found. std::endl does not avoid buffering. It flushes whatever is in the buffer. If you need to avoid buffering, use setf(ios_base::unitbuf). That sets the stream to flush after each insertion. That's the default setting for std::clog. The reason for doing this is that the less stuff being held in the buffer, the greater the chance that critical data will have been written to the stream when the program crashes.

Flushing also matters for interactive programs: if you write a prompt to std::cout, it's a Good Thing if that prompt shows up on the display before the program starts waiting for input. That's done automatically when you use std::cout and std::cin, unless you've messed with the synchronization settings.

Many programmers seem to use std::endl as a fancy way of spelling '\n', but it's not. You don't need to flush the output buffer every time you write something to it. Let the OS and the standard library do their jobs; they'll take care of getting the output to the appropriate place in a timely manner. A simple std::cout << '\n'; is all that's needed to put a newline into the output, and sooner or later, that will show up on the display. If you need to have it show now, typically because you've written all of the output for the time being and don't want to leave the displayed information incomplete, use std::endl after the last line of the output.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165