#056 –  cout, cerr, clog: The three output streams

Everyone is familiar with std::cout. However, C++ provides 2 other output streams that can be used for a different purpose.

Three things to take away:

  • std::cout carries user-facing output
  • std::cerr carries diagnostics and errors
  • std::clog is std::cerr‘s buffered cousin

What’s different between the three streams

All three streams write text to the program’s output, but they differ in two important ways:

  1. The destination the OS routes them to
  2. How aggressively they flush their buffers

All three streams write text to the program’s output, but they differ in two important ways: the destination the OS routes them to, and how aggressively they flush their buffers.

StreamDestinationBufferingTypical use
std::coutstdout (fd 1)BufferedNormal program output
std::cerrstderr (fd 2)UnbufferedErrors, urgent diagnostics
std::clogstderr (fd 2)BufferedLogs, high-volume tracing

std::cout is the workhorse. It buffers its output for performance — characters accumulate in memory and are written to the terminal in chunks. The flush usually happens automatically (when the buffer fills, when the program exits, when std::endl is used)

std::cerr is unbuffered, which means every write is sent to the OS immediately. This ensures the error messages are displayed immediately, even if the program crashes. With std::cerr, the message is pushed to the console the millisecond the code executes. This is extremely useful in capturing all debug output (at the cost of some performance). Use std::cerr for diagnostic information, warnings and errors – information that isn’t useful to the user and that should be abstracted.

// Validate input
if (monthNumber < 1 || monthNumber > 12) {
	std::cerr << "Please enter a valid month!\\n";
	return;
}

std::clog writes to the same destination as std::cerr (the standard error stream), but is buffered like std::cout. Use it for high-volume diagnostics.

When to use std::clog

std::clog is the least-used of the three but earns its place in programs that emit a lot of diagnostic output. Imagine a long- running data processor that logs each batch it completes:

for (const auto& batch : batches) {
    std::clog << "Processing batch " << batch.id << '\\n';
    process(batch);
}

Using std::cerr here would flush after every line — many thousands of system calls over the course of the run. Using std::cout pollute the program output, breaking redirection.

std::clog is the right answer: buffered for performance, but routed to stderr so the user can filter or capture it separately from real results.

The trade-off is that buffered output may not appear until the buffer fills or the program exits cleanly

In Conclusion

C++ provides three output streams because programs produce three kinds of output:

  1. Results
  2. Errors
  3. Logs

Use std::cout for the program’s real output, std::cerr for errors that must reach the user immediately, and std::clog for high-volume diagnostics where flushing every line would hurt