Table of Contents
To minimize the time you have to wait on the compiler, it's good to
only include the headers you really need. Many people simply include
<iostream>
when they don't
need to -- and that can penalize your runtime as well.
Here are some tips on which header to use
for which situations, starting with the simplest.
<iosfwd>
should be included whenever you simply need the name
of an I/O-related class, such as "ofstream
" or
"basic_streambuf
".
Like the name implies, these are forward declarations.
(A word to all you fellow old school programmers:
trying to forward declare classes like "class istream;
"
won't work.
Look in the <iosfwd>
header
if you'd like to know why.) For example,
#include <iosfwd> class MyClass { .... std::ifstream& input_file; }; extern std::ostream& operator<< (std::ostream&, MyClass&);
<ios>
declares the base classes for the entire I/O stream hierarchy,
std::ios_base
and std::basic_ios<charT>
,
the counting types std::streamoff and std::streamsize,
the file positioning type std::fpos,
and the various manipulators like std::hex
,
std::fixed
, std::noshowbase
,
and so forth.
The ios_base
class is what holds the format
flags, the state flags, and the functions which change them
(setf()
, width()
,
precision()
, etc).
You can also store extra data and register callback functions
through ios_base
, but that has been historically
underused. Anything
which doesn't depend on the type of characters stored is consolidated
here.
The class template basic_ios
is the highest
class template in the
hierarchy; it is the first one depending on the character type, and
holds all general state associated with that type: the pointer to the
polymorphic stream buffer, the facet information, etc.
<streambuf>
declares the class template basic_streambuf
, and
two standard instantiations, streambuf and
wstreambuf. If you need to work with the vastly useful and
capable stream buffer classes, e.g., to create a new form of storage
transport, this header is the one to include.
<istream>
and <ostream>
are the headers to include when you are using the overloaded
>>
and <<
operators,
or any of the other abstract stream formatting functions.
For example,
#include <istream> std::ostream& operator<< (std::ostream& os, MyClass& c) { return os << c.data1() << c.data2(); }
The std::istream and std::ostream classes are the abstract parents of the various concrete implementations. If you are only using the interfaces, then you only need to use the appropriate interface header.
<iomanip>
provides "extractors and inserters that alter information maintained by
class ios_base
and its derived classes,"
such as std::setprecision
and
std::setw
. If you need
to write expressions like os << setw(3);
or
is >> setbase(8);
, you must include
<iomanip>
.
<sstream>
and <fstream>
declare the six stringstream and fstream classes. As they are the
standard concrete descendants of istream and ostream,
you will already know about them.
Finally, <iostream>
provides the eight standard global objects
(cin
, cout
, etc). To do this correctly, this
header also provides the contents of the
<istream>
and
<ostream>
headers, but nothing else. The contents of this header look like:
#include <ostream>
#include <istream>
namespace std
{
extern istream cin;
extern ostream cout;
....
// this is explained below
static ios_base::Init __foo; // not its real name
}
Now, the runtime penalty mentioned previously: the global objects
must be initialized before any of your own code uses them; this is
guaranteed by the standard. Like any other global object, they must
be initialized once and only once. This is typically done with a
construct like the one above, and the nested class
ios_base::Init
is
specified in the standard for just this reason.
How does it work? Because the header is included before any of your code, the __foo object is constructed before any of your objects. (Global objects are built in the order in which they are declared, and destroyed in reverse order.) The first time the constructor runs, the eight stream objects are set up.
The static
keyword means that each object file compiled
from a source file containing
<iostream>
will have its own
private copy of __foo. There is no specified order
of construction across object files (it's one of those pesky NP complete
problems that make life so interesting), so one copy in each object
file means that the stream objects are guaranteed to be set up before
any of your code which uses them could run, thereby meeting the
requirements of the standard.
The penalty, of course, is that after the first copy of __foo is constructed, all the others are just wasted processor time. The time spent is merely for an increment-and-test inside a function call, but over several dozen or hundreds of object files, that time can add up. (It's not in a tight loop, either.)
The lesson? Only include
<iostream>
when you need
to use one of
the standard objects in that source file; you'll pay less startup
time. Only include the header files you need to in general; your
compile times will go down when there's less parsing work to do.