The C++ Standard Library includes templates for data stream input/output. Before the current ANSI/ISO standard, most C++ compilers were delivered with a class library commonly known as the iostreams library. In this manual, we refer to this library as the traditional iostreams, in contrast to the standard iostreams that are now part of the ANSI/ISO C++ Standard Library. The standard iostreams are to some extent compatible with the traditional iostreams, in that the overall architecture and the most commonly used interfaces are retained. Chapter 45 describes the incompatibilities in greater detail.
We can compare the standard iostreams not only with the traditional C++ iostreams library, but also with the I/O support in the Standard C Library. Many former C programmers still prefer the input/output functions offered by the C library, often referred to as C stdio. Their familiarity with the C library is justification enough for using the C stdio instead of C++ iostreams, but there are other reasons as well. For example, calls to the C functions printf() and scanf() are admittedly more concise with C stdio. However, C stdio has drawbacks, too, such as type insecurity and inability to extend consistently for user-defined classes. We'll discuss these in more detail in the following sections.
Let us compare a call to stdio functions with the use of standard iostreams. The stdio call reads as follows:
int i = 25; char name[50] = "Janakiraman"; fprintf(stdout, "%d %s", i, name);
It correctly prints: 25 Janakiraman.
But what if we inadvertently switch the arguments to fprintf()? The error is detected no sooner than run time. Anything can happen, from peculiar output to a system crash. This is not the case with the standard iostreams:
std::cout << i << ' ' << name << '\n';
Since there are overloaded versions of the shift operator operator<<(), the right operator is always called. The expression std::cout << i calls std::ostream::operator<<(int), and std::cout << name calls std::ostream::operator<< (std::ostream&, const char*). Hence, the standard iostreams are typesafe.
Another advantage of the standard iostreams is that user-defined types can be made to fit in seamlessly. Consider a type Pair that we want to print:
struct Pair { int x; string y; }
All we need to do is overload operator<<() for this new type Pair, and we can output pairs this way:
Pair p = { 5, "May" }; std::cout << p;
The corresponding operator<<() can be implemented as:
std::ostream& operator<<(std::ostream& o, const Pair& p) { return o << p.x << ' ' << p.y; }