Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should std::endl always be used?

Tags:

c++

I am jumping from C into C++ with the help of the book C++ Primer (5th edition) where the author states the following:

Programmers often add print statements during debugging. Such statements should always flush the stream. Otherwise, if the program crashes, output may be left in the buffer, leading to incorrect inferences about where the program crashed.

But posts online suggest otherwise; some say constant flushing of the buffer is bad for the program and causes performance issues.

My questions:

  1. When should you use std::endl?
  2. Is the author wrong or did I misunderstand any part of what he stated?
  3. Can you give any real-world scenarios where flushing the output stream is necessary?

P.S.

  1. What does flushing the buffer mean?
like image 235
psrag anvesh Avatar asked Feb 23 '16 15:02

psrag anvesh


People also ask

Do you need std :: endl?

The only difference is that std::endl flushes the output buffer, and '\n' doesn't. If you don't want the buffer flushed frequently, use '\n' . If you do (for example, if you want to get all the output, and the program is unstable), use std::endl .

Is it compulsory to use Endl in C++?

To be clear, the vast majority of the time, you should not use endl . See also this answer + comments. remember end-of-line is "\r\n" on a DOS/Windows platform and bare "\r" on some (all?) Mac platform, too.

Is it better to use Endl or \n?

Both endl and \n serve the same purpose in C++ – they insert a new line. However, the key difference between them is that endl causes a flushing of the output buffer every time it is called, whereas \n does not.

Is Endl bad practice?

It is a common practice to use std::endl to print newlines while using cout. For small programs with very little I/O operations this practice is acceptable, but if the bulk of I/O operations increase, then the efficiency of the program is compromised.


4 Answers

Debug output should be written to std::cerr; it's unit buffered, so every character gets flushed. There is rarely a need for std::endl, and getting in the habit of using it will lead to mysteriously slow code. Just use '\n' unless you know you need to flush the buffer.

like image 179
Pete Becker Avatar answered Oct 05 '22 09:10

Pete Becker


Point 4 and Point 3

Starting with point 4 because everything else hinges on it and point 3 because it is tightly related.

When you flush the stream, you are taking all data stored by the stream and writing it to the underlying medium represented by the stream.

When it is flushed it is done, committed and ready to be observed by the outside world (More or less. The operating system and the hardware backing the stream may also delay the write, but there isn't much you can do about that). You can't read it until it has been flushed. If it's never flushed, you can't read it.

The thing is you do not want to write to IO very often because anything that goes out of the CPU takes an ungodly amount of time compared to that which stays inside the CPU. Tens of thousands of times slower sometimes. Inside the CPU you have gigahertz and parallel buses moving data 32 or more bits at a time. Outside you have megahertz often moving a single bit at a time.

Take a file as a classic example. Not only is drive access running at a fraction of a speed of the CPU, but if every byte goes directly to a disk, then for every byte you may have to

  1. find that byte's analogue on the disk.
  2. load the sector around that byte into memory. So instead of moving one byte, you may be moving a few hundred or thousand. Usually 512 bytes or 4096 bytes.
  3. write the byte into the sector in memory
  4. write the sector in memory back to the disk

Brutal. Imagine doing this a few hundred or a few thousand times to write a single string. But what if you only wrote the string when it got too big to hold or you were done? What if you wrote in sectors rather than bytes? Then you could

  1. find that byte's analogue's sector on the disk.
  2. write the stored sector to the disk

One operation for potentially thousands of byte in one shot.

Point 2

Point 2 goes back to point four/three's you can't read what you don't flush. If you want to see a particular output on the screen and you want to see it now, you flush. If you want to get a debug message out before the program crashes, and likely terminates without getting those last few absolutely essential messages onto the screen, you flush. History is full of programmers looking in the wrong place for a bug because they didn't get those last few unflushed error messages.

You are trading program speed for the relative certainty that you will see an important message when you need to see it.

Point 1

Point 1 calls back to point 2. std::endl is both an end of line and an instruction to flush the stream. You use it sparingly and only when you need both an end of line and a flush. If you don't need a flush, just send and end of line: '\n'.

Take Pete Becker's advice and use std::cerr for errors and debugging where possible. That's what it was built for. It operates on brute force and ignorance. It's painful. It's slow. And it almost always works.

like image 35
user4581301 Avatar answered Oct 05 '22 09:10

user4581301


By default std::cout is linked to stdout, which is...

fully buffered if and only if the stream can be determined not to refer to an interactive device.

(C99, 7.19.3 Files, paragraph 7.)

This means, if your output is sent to terminal, std::endl vs. "\n" makes no difference in the first place. ;-)


Regarding your actual question:

Both is true:

  • unflushed output buffers can lead to incorrect inferences about where the program crashed
  • flushing of output buffers affects performance

This only becomes a problem once you add "always".

When should you use std::endl?

When you want to flush the buffer.

Is the author wrong or did I miss understand any part of what he stated?

I think absolute quantifiers like "always", "all", "never" etc. should be taken with a grain of salt as far as style / design / etc. is concerned.

(Exception: Never invoke undefined behaviour. ;-) )

Can you give any real world scenarios for actual need of flushing the output stream?

Whenever not having the latest output actually appear would not be acceptable. Whether this is the case in any given scenario is a judgement call.

Personally, I would consider production / transaction logs to be more critical than debug logs...

like image 34
DevSolar Avatar answered Oct 05 '22 08:10

DevSolar


Both the author and the posts are right.

stream << std::endl is actually stream << '\n' << std::flush. Explicit flushing has performance drawbacks, and this is why you shouldn't use it in performance-critical situations. You rarely think about such negligible performance issues while debugging, so it actualy is a good practice to explicitly flush debug output.

like image 27
lisyarus Avatar answered Oct 05 '22 09:10

lisyarus