A case of an overloaded abstraction.

Or when new line is more than what it says.

I remember my first day of professional C++ career many years ago - I was young, passionate and ready for action. I dug into the codebase looking for some immediate wins hoping to impress my new colleagues. As part of this exercise I’ve noticed a recurring pattern of \n usage for in many helper functions and production code like in the example below

instead of expected

Willing to impress my colleagues with my “expert” C++ knowledge I have submitted a change request to replace all usages of \n with std::endl, but instead of quick approval I’ve got pointers to C++ documentation that clearly states:

Inserts a newline character into the output sequence os and flushes it as if by calling os.put(os.widen('\n')) followed by os.flush().

So there is a significant difference between a plain \n which does not require a flush, at least unless standard library choses to do so anyways, and std::endl, that always flushes the buffer causing unnecessary overhead for use-cases that do not require flushing, e.g. non-critical logging.

In assembly this is represented as

for \n version and

for std::endl version.

Apparently this issue is widespread enough that C++ Core Guidelines includes explicit advice on avoiding it:

SL.io.50: Avoid endl

Reason

The endl manipulator is mostly equivalent to '\n' and "\n"; as most commonly used it simply slows down output by doing redundant flush()s. This slowdown can be significant compared to printf-style output.

While performance impact depends on the environment, for cases that require buffer flushing, I would prefer using explicit std::flush to better communicate the intent and improve readability. Also, in general, combining multiple effects into a single abstractions should be avoided, especially when it’s not obvious and results in confusion.