diff --git a/bot-articles/endl.md b/bot-articles/endl.md deleted file mode 100644 index bf771e7..0000000 --- a/bot-articles/endl.md +++ /dev/null @@ -1,38 +0,0 @@ -# About `std::endl`, Buffers, and Flushing - -I/O in C++ (**[std::cout][cout]**, i.e. **[std::ostream][ostream]**) is *buffered*, which means that not every character -you write to the stream is instantly written through to the terminal/disk. Doing so would be very slow. - -Instead, there is a buffer of e.g. 8192 bytes and when it's full, -all data is written through to the OS, i.e. *flushed* in one syscall. -This is much more efficient. - -[cout]: https://en.cppreference.com/w/cpp/io/cout -[ostream]: https://en.cppreference.com/w/cpp/io/basic_ostream - - -## What Is *Flushing*? -*Flushing* means that all characters currently in the buffer are written through, -and the buffer is cleared. - -Use **[<< std::flush][ioflush]** -or **[.flush()][oflush]** -to flush, or use -**[std::cerr][cerr]**, which is unbuffered. - -[ioflush]: https://en.cppreference.com/w/cpp/io/manip/flush -[oflush]: https://en.cppreference.com/w/cpp/io/basic_ostream/flush -[cerr]: https://en.cppreference.com/w/cpp/io/cerr - - -## `std::endl` -**[std::endl](https://en.cppreference.com/w/cpp/io/manip/endl)** -is an -[I/O manipulator](https://en.cppreference.com/w/cpp/io/manip) which writes a newline character to the stream, and -flushes it. - -Use `<< '\n'` if you don't need to flush. - -## See Also -<:stackoverflow:1074747016644661258> -["std::endl" vs "\n"](https://stackoverflow.com/q/213907/5740428) diff --git a/wiki/resources/cpp/endl.md b/wiki/resources/cpp/endl.md new file mode 100644 index 0000000..b8fbb07 --- /dev/null +++ b/wiki/resources/cpp/endl.md @@ -0,0 +1,90 @@ +--- +bot_article: | + # `std::endl`, Buffers, and Flushing + + Both `std::endl` and `'\n'` write a newline to an output stream. The difference is that `std::endl` also *flushes* the + stream. + + C++ I/O streams are *buffered*: characters are collected in a buffer and written in bulk for efficiency. *Flushing* + forces the buffer contents to be written immediately. + + Recommendation: **Prefer `'\n'` over `std::endl`** unless you specifically need to flush. That said, in most programs + this difference is negligible - it only matters when producing lots of output. +--- + +# `std::endl`, Buffers, and Flushing + +Both `'\n'` and [`std::endl`](https://en.cppreference.com/w/cpp/io/manip/endl) write a newline, but `std::endl` also +flushes the stream. Recommendation: **Prefer `'\n'`** when you don't need the flush. + +```cpp +std::cout << "Hello" << std::endl; // Newline + flush +std::cout << "Hello" << '\n'; // Just a newline (usually sufficient) +``` + +That said, in most programs this difference is negligible and it's not something to worry about. + +## I/O Buffering + +I/O in C++ is _buffered_. Characters you write to a stream aren't instantly sent to the terminal or disk. Instead, +they're collected in an internal buffer and written later. This batching makes I/O more efficient by reducing system +call overhead. + +_Flushing_ forces all buffered characters to be written immediately. You can flush manually with `<< std::flush` or +`.flush()`. Flushing also happens automatically when your program exits (but not through `abort` or `_exit`). + +## Buffering Modes + +Streams can operate in different buffering modes, which affect when automatic flushing occurs: + +- **Fully buffered**: Flushes only when the buffer is full. Typical for file output. +- **Line buffered**: Flushes when a newline is written (or when the buffer is full). Typical for terminal output. +- **Unbuffered**: No buffering; each write goes directly to the destination. `std::cerr` uses this by default. + +Because terminal output is typically line-buffered, `'\n'` triggers a flush automatically, so `std::endl` and `'\n'` +often behave the same for console output. + +File output is typically fully buffered, so `'\n'` won't flush. This is where the distinction matters most: + +```cpp +// Flushes after every line (slower for lots of output) +for (int i = 0; i < 10000; ++i) { + file << i << std::endl; +} + +// Buffer flushes only when full (more efficient) +for (int i = 0; i < 10000; ++i) { + file << i << '\n'; +} +``` + +For occasional output, the difference won't matter. In tight loops writing to files, it can be noticeable. + +## When to Flush + +Explicit flushing is useful when you need output to appear immediately: + +- **Progress indicators**: Partial lines that should display before the next operation +- **Debugging output**: Ensuring messages appear before a potential crash +- **Logging**: When log messages must be written immediately + +```cpp +std::cout << "Processing... "; +std::cout.flush(); // Show "Processing... " before the work starts +do_lengthy_work(); +std::cout << "done.\n"; +``` + +For interactive prompts, reading from `std::cin` automatically flushes `std::cout`, so explicit flushing is often +unnecessary. + +For debugging, consider [`std::cerr`](https://en.cppreference.com/w/cpp/io/cerr) instead, which is unbuffered by +default. + +## See Also + +- [std::cout](https://en.cppreference.com/w/cpp/io/cout) +- [std::endl](https://en.cppreference.com/w/cpp/io/manip/endl) +- [std::flush](https://en.cppreference.com/w/cpp/io/manip/flush) +- [std::cerr](https://en.cppreference.com/w/cpp/io/cerr) +- ["std::endl" vs "\n"](https://stackoverflow.com/q/213907/5740428) on Stack Overflow diff --git a/wiki/resources/sidebar.ts b/wiki/resources/sidebar.ts index 7f50d9d..ff3b190 100644 --- a/wiki/resources/sidebar.ts +++ b/wiki/resources/sidebar.ts @@ -69,6 +69,10 @@ const sidebar = [ text: "Overloading Stream Operators", link: "/resources/cpp/stream-operators", }, + { + text: "std::endl, Buffers, and Flushing", + link: "/resources/cpp/endl", + }, ], collapsed: true, },