iostream
is Awful
Pretty much every piece of iostream
is damaged beyond repair. I honestly can't believe people still
recommend it for IO in C++. (At the very least, it's what's taught in intro C++ courses.) I'm going to just
assume anyone reading is familiar with iostream
and just dive right in.
The first obvious problem is the global state. Whose brain-dead idea was this? Consider the following code:
cout << hex << 0x10 << endl;
f();
cout << dec;
Seems straightforward, but what if f
throws an exception? Then we're fucked. Everything is in
hex because that last line never runs. Or, more realistically, what if we simply forget that last line?
Compare this with printf
:
printf("%x\n", 0x10);
f();
Nice and simple. No possible way to forget to reset to decimal, because there's no global state we have to worry about.
Look up some benchmarks of iostream
vs. printf
. I'll wait. One reason for that?
Every <<
is a separate virtual function call, compared with the single function call
for printf
. And each of those involves syscalls.
Syncing iostream
with stdio
by default obviously doesn't help things, but you'll see
a performance difference either way.
Obviously, IO is normally a bottleneck anyways, so this point is fairly minor compared to some other ones below.
Say I've got a bitfield and I want to mask it and print the result. With printf
, that looks like
this: printf("%x\n", f & m);
. Fairly straightforward. With iostream
, we need to do
this: cout << hex << f & m << endl << dec;
.
Except, wait a minute. That doesn't compile. Why not? Oh, right <<
is a bitshift operator as
well, so it has the wrong precedence compared with &
. Oops. Maybe the Java people are right
about operator overloading.
Under POSIX, any single call to printf
is an atomic operation, meaning you'll never have
output from one thread intermixed with output from another. With iostream
, something like
cout << "A" << "B" << endl;
is 3 function calls, and you could get arbitrary
output from another thread printed in between any of them. Perfect.
printf
isn't Type-safe"
It's $current_year. I've never used a compiler that will let me (a) compile printf
with anything
besides a string literal and (b) compile any type-mismatches in printf
. (Yes, this is with
-Wall -Werror
, but if you're not compiling with those already you have bigger problems.) I've
literally never had a type error from using printf
. This is, by far, the weakest excuse for not
using printf
I've ever heard.
This is the only advantage of iostream
as far as I'm concerned. Just overload
<<
for whatever type you need, boom, custom printing for your type. Quite elegant. Except for
then you need to use iostream
. Dammit.
In practice, I've rarely ever actually overloaded <<
for custom printing, but that's besides
the point.
printf
?"
Not necessarily. While I would prefer using printf
to using iostream
, these aren't the
only options. Lots of libraries support a type-safe and extensible version of printf
. C++20 is
bringing us some really nice formatting options.
All I'll say here is that it's pretty telling that most languages have something close to printf
,
but I can't think of a language that copied iostream
.