Recently I started a class at my university which teaches the C++ programming language. It is a fun language I have a bit of experience with already and I’ve been going through the textbook’s various exercises and have picked up on a few anti-patterns the textbook is encouraging. In the practice problems you build an std::ostream (https://en.cppreference.com/w/cpp/header/ostream) with the data you want to show the user and then output it to the screen with std::cout (https://en.cppreference.com/w/cpp/io/cout). The exercises help the student learn different aspects of the programming language but all use this output format.

Summary

\n occupies a byte in memory to represent a new in the string whereas «endl instead flushes the output buffer immediately but does not need to store a new line in the stream until its output. The good news is once you’re done with the stream and flush the output buffer you can recover the memory. A few extra bytes in memory can improve your program’s speed by avoiding unnecessary flushes of the output buffer. If you take away anything from this post it’s that using \n instead of std::endl will make your programs ever so slightly faster :-)

When does the output buffer flush?

There are several situations in which std:cout, the operating system, or compiler will setup the output buffer to flush. A few I read about include that: A flush occurs when the program exits, when std::cin is called after a std::cout, when the compiler/os runtime sees the buffer is running out of memory, when you append << std::endl to a ostream, or when you append << std::flush to a ostream. A general rule of thumb is if you want to see the output immediately call <<std::flush.

The C++ standard library provides std::unitbuf and std::nounitbuf (https://en.cppreference.com/w/cpp/io/manip/unitbuf) to explicitly enable or disable automatic flushing of the output buffer. Although any I/O from std::cout or std::cin will force a flush due to the nature of how the functions work. While they occur naturally often, there’s no need to force it to happen unnecessarily as it can have an impact on your program’s performance (ever so slightly but still worth discussing).

Drawbacks of not flushing the output buffer immediately

If you call a function in your stream vs calling it when declaring a variable it might make debugging harder to determine where code has a logical or syntaxial error. I prefer to call functions at variable declaration so in my stream it’s variables I already know are as expected and a debugger can confirm the values with a breakpoint if there’s an issue. That said you also experience this unless you call std::endl after every function call so it’s not unique to users of \n (C style new lines).

On the subject of memory management

My understanding here is that unless you create a variable like ostream myOutput << "some text" << endl; it’s freed automatically after it’s passed to cout although I may be missing part of the picture here. I’m new to memory management in C so I don’t understand all of the nuances yet. delete myOutput would work too to delete the variable and its content. The point remains the few extra bytes are stored for a short amount of time, eventually they have to be cleaned up.

The textbook’s examples

So far the examples I’ve read recommend using «endl while building ostreams (how the « creates a string internally to pass to cout) which are passed to cout. These examples would be something like cout « “Hi my name is: " « myName « endl « “And my age is: " « age « endl; whereas the first endl could instead of be a “\n” until the output is flushed at the end of the statement. This is bad because it uses extra CPU cycles to immediately flush the output buffer on every new line operation where you could use \n if you do not need to immediately flush the output buffer. Flushing at the end of a statement (when it’s built and ready to show to the user) makes more sense than flushing as you build the information to send to the user’s screen.

Concerning old style debugging

With cout statements instead of GDB or another debugger it’s typically safe to only flush at the end of a single cout statement vs on every new line. This does have the consequence of using an extra byte of memory per new line (but can be recovered later). However using endl is slower because it forces the system to flush the output buffer. In most of the examples building a string with a few new lines this means that the program must stop, perform the blocking operation of flushing the output buffer then resume, whereas for a situation where you are only outputting a single line with a few \ns you could wait until the string is built then either let the system output it when it’s ready or force a flush with cout « flush;

This probably isn’t a real world issue

The average laptop has at least 4GB of RAM or 4e+9 Bytes from a quick search on Amazon for laptops. Taking a few of them will have negligible effect and you can always free that memory if you need it for something else, no need to keep a string in memory after it’s been output to the screen. You could make the counterargument that CPUs are also really fast so tiny blocking operations like this are not an issue in the real world. That being said let’s continue with the data.

How to output a string with a new line in C++

When outputting a string with a new line you have the option of either using \n and flushing the ostream manually or using std::endl. I’ve demonstrated this in the code example below.

#include <iostream>

int main() {

    // Hello World! ending with a new line
    std::cout << "Hello World!\n" << std::flush;

    // Also Hello World! ending with a new line
    std::cout << "Hello World!" << std::endl;
    return 0;
}

In this example the difference is subtle and being such a small string std::endl may be more appropriate as there is not a \n to occupy a byte of a memory and the program does not do anything useful. Let’s consider a larger example, the first example uses std::endl whereas the second example uses \n and manually invokes std::flush where applicable.

Using std::endl (Output buffer is flushed three times)

#include <iostream>

int main() {

    std::string name = "Catgirl";
    std::string favoriteColor = "Purple";
    std::string favoriteDrink = "Coffee";

    std::cout << "Hi class my name is "
        << name
        << "!"
        << std::endl
        << "My favorite color is "
        << favoriteColor
        << "!"
        << std::endl
        << "I like to drink "
        << favoriteDrink
        << "!"
        << std::endl;

    return 0;
}

Using \n and std::flush (Output buffer is flushed one time)

#include <iostream>

int main() {

    std::string name = "Catgirl";
    std::string favoriteColor = "Purple";
    std::string favoriteDrink = "Coffee";

    std::cout << "Hi class my name is " 
        << name 
        << "!"
        << "\n" 
        << "My favorite color is " 
        << favoriteColor 
        << "!"
        << "\n"
        << "I like to drink "
        << favoriteDrink
        << "!"
        << "\n"
        << std::flush;

    return 0;
}

What the data says

I modified my program slightly to use timers. This program was built and tested inside of Visual Studio 2019 with Microsoft’s C++ Compiler, your results may vary across platforms and compilers. To account for variations each test is run three times. I also tested both 32-bit and 64-bit builds in both DEBUG and RELEASE configurations.

Timer for Using std::endl (Output buffer is flushed three times)

32-bit DEBUG BUILD:
   672 Microseconds
   637 Microseconds
   898 Microseconds

32-bit RELEASE BUILD:
   605 Microseconds
   584 Microseconds
   642 Microseconds

64-bit DEBUG BUILD:
   712 Microseconds
   562 Microseconds
   654 Microseconds

64-bit RELEASE BUILD:
   896 Microseconds
   759 Microseconds
   629 Microseconds

#include #include

int main() { auto start = std::chrono::high_resolution_clock::now();

std::string name = "Catgirl";
std::string favoriteColor = "Purple";
std::string favoriteDrink = "Coffee";

std::cout << "Hi class my name is "
    << name
    << "!"
    << std::endl
    << "My favorite color is "
    << favoriteColor
    << "!"
    << std::endl
    << "I like to drink "
    << favoriteDrink
    << "!"
    << std::endl;

auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);

std::cout << "Time taken by function: "
    << duration.count() << " microseconds" << std::endl;
return 0;

}


### Timer for Using \\n and std::flush (Output buffer is flushed one times)

32-bit DEBUG BUILD: 617 Microseconds 699 Microseconds 583 Microseconds

32-bit RELEASE BUILD: 634 Microseconds 595 Microseconds 623 Microseconds

64-bit DEBUG BUILD: 860 Microseconds 784 Microseconds 841 Microseconds

64-bit RELEASE BUILD: 613 Microseconds 687 Microseconds 705 Microseconds

#include <iostream>
#include <chrono>

int main() {
    auto start = std::chrono::high_resolution_clock::now();

    std::string name = "Catgirl";
    std::string favoriteColor = "Purple";
    std::string favoriteDrink = "Coffee";

    std::cout << "Hi class my name is "
        << name
        << "!"
        << "\n"
        << "My favorite color is "
        << favoriteColor
        << "!"
        << "\n"
        << "I like to drink "
        << favoriteDrink
        << "!"
        << "\n"
        << std::flush;

    auto stop = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);

    std::cout << "Time taken by function: "
        << duration.count() << " microseconds" << std::endl;
    return 0;
}
```

### Graphing the data I collected

I put all of the data into a spreadsheet so I could work on charting it in a few ways. I found our data shows that `std::endl` has a 687.5 Microsecond Average where as `\n and std::flush` has a 686.75 Microsecond Average meaning you save 0.75 Microseconds on average by using the `\n and std::flush` method. However small of a difference, time is saved when don't flush the output buffer until its necessary necessary.

![](https://i.imgur.com/mTWBs3x.png)

This is a pretty chart. I have no idea how to read it.

In conclusion
-------------

The difference is really really small and until your application is large you probably won't notice a difference. I hope this post brings awareness to the difference between using `std::endl` and `\n with std::flush` to output lines of text.