Does std::endl << std::flush have a purpose?
Asked Answered
H

3

12

std::flush right after a std::endl is used all over the legacy code I am looking at. When I first saw this, my thought was it is redundant from looking at the description of std::endl and std::flush at:

http://en.cppreference.com/w/cpp/io/manip/endl

http://en.cppreference.com/w/cpp/io/manip/flush

Here is an example of what I am seeing in the legacy source code:

std::cout << "Generic Notification" << std::endl << std::flush;

But, as many senior software developers have seen this code throughout the years, I am wondering if there is some detail I am missing. Is there any purpose to having a std::flush after a std::endl?

Hangnail answered 5/6, 2018 at 18:46 Comment(10)
if it wasnt std::cout but some other stream there might be a reason...Sidewalk
@user463035818 And what would that be? std::endl is defined as "end line & flush."Principally
@Angew if I write my own stream that has operator<< overloads for std::endl and std::flush i can make them work any way I want, no?Sidewalk
@user463035818 Oh, you meant if it was not a standard stream at all. Yes, then indeed it could make sense (if the stream implementor's logic was twisted enough). I interpreted your comment as comparing std::cout to other std streams (e.g. a std::ofstream instance).Principally
@Angew I just considered the chance that OP replaced whatever stream it was in the original code with std::cout for the sake of a mcve. Of course even for a custom streamlike object the flush should not have any use in that placeSidewalk
@user463035818 For the mcve I just used std out, but also there are calls to std error in the legacy code that use this std::endl << std::flush.Hangnail
my first comment more precise: There might be a reason for the flush if it wasnt a standard stream, though it still wouldnt be a good reason, because a stream that does not flush on endl can be considered brokenSidewalk
maybe just noone ever had the cochones to tell the seniors that this makes no sense ;)Sidewalk
@user463035818 haha, after getting the feedback from SO, now I willHangnail
@user463035818: Maybe someone just did sed -ri 's/std::cout (<< .*);$/std::cout \1 << std::flush;/' on the source at some point.Wrightson
J
18

There's no purpose for it.

If I had to speculate on why your legacy code contains these lines, there are a few possibilities, starting with (what I consider to be) the most probable scenarios:

  • Someone added the explicit call to std::flush mistakenly, and the senior developers didn't consider it a problem needing fixing
  • The code originates from a time before the C++ standard was widely adopted, and in that time, the local compiler's implementation of std::endl did not trigger a flush, which meant that your senior developers were (correctly) understanding that it was necessary
  • An older version of the C++ standard might not have required std::endl to trigger a flush
  • Your senior developers are mistaken about the behavior of std::endl.
  • Your execution environment is a strange behemoth that actually requires output to be flushed twice before the desired result can be expected.
Jijib answered 5/6, 2018 at 18:51 Comment(3)
Silly things like this can also appear when text search & replace is performed on source code, such as: replace << '\n'with << std::endlMammillate
Good answer, but "an older version of the C++ standard…" – no, C++98 was the first standard, and it did require a flush. At best, some early version of the standard library may have behaved differently, though I doubt it. BTW, I can think of a reason why they would use endl instead of '\n’ despite not realizing it flushes, which is a system that does not have LF line terminator (most likely Windows). Of course this is not necessary on cout/cerr, nor a text mode ofstream, and then again endl doesn't even help for a binary ofstream, but that may have been the mistaken reasoning.Oval
I particularly like the last scenario.Coloring
W
8

I'll add to the other valid answers that, very often, there isn't a good purpose for neither std::flush nor std::endl.

Basically, std::endl = start a new line + flush the stream. A lot of people, though, tend to end their lines with std::endl because it "sounds right" - end the line. But we actually rarely need to flush the output stream. Sometimes we do (e.g. when we're expecting a user's reply to the string, or it's important to monitor our output with minimal delay) - but that's the exception, not the rule.

So, it might take a bit of getting used to, but we should really default to simply:

std::cout << bunch_of_stuff << '\n';

and that's that!

Wrightson answered 5/6, 2018 at 19:6 Comment(2)
Yes! Use std::cerr if you need output to be flushed to a terminal.Earache
When testing / debugging it's handy that your output is flushed.Rattly
A
5

In a standards-compliant environment, std::flush serves no useful purpose in this code.

Whoever wrote this either didn't fully understand the semantics of std::endl, or were working around some limitation of their compiler or execution environment.

Arrowwood answered 5/6, 2018 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.