What's the difference between endl and'\n' ?(转)

Folks often see output statements like the two below, and then want to know what the difference is:

#include <iostream>

int main()
{
  int i = 99;
  std::cout << i << '\n'; // A
  std::cout << i << std::endl; // B
  return 0;
}

In short, using '\n' is a request to output a newline. Using endl also requests to output a newline, but it also flushes the output stream. In other words, the latter has the same effect as (ignoring the std:: for now):

cout << i << '\n'; // C: Emit newline
cout.flush(); // Then flush directly

Or this:

cout << i << '\n' << flush; // D: use flush manipulator

In a discussion like this, it's worth pointing out that these are different too:

cout << i << '\n'; // E: with single quotes
cout << i << "\n"; // F: with double quotes

In specific, note that Es last output request is for a char, hence operator <<(ostream&, char) will be used. In Fs case, the last is a const char[2], and so operator <<(ostream&, const char *) will be used. As you can imagine, this latter function will contain a loop, which one might argue is overkill to just print out a newline. Some of these same point also apply to comparing these three lines of code, which all output h, i and newline, somewhere in some way:

cout << "hi\n"; // G
cout << "hi" << '\n'; // H
cout << "hi" << "\n"; // I

By the way, although these examples have been using cout, it does not matter which stream is being used. Also, note that line A may also cause a flush operation to occur in the case where the newline character just happens to be the character to fill up the output buffer (if there is one, that is, the stream in question may happen to not be buffered).

In conclusion, which of these should you use? Unless performance is absolutely necessary, many favor using endl, as many find that just typing endl is in most cases easy and readable.

Here's a bit more technical information for those so inclined. As it turns out, endl is called an iostreams manipulator. In reality, it is a function generated from a template, even though it appears to be an object. For instance, retaining its semantics, it might look like this:

inline ostream &std::endl(ostream& OutStream)
{
  OutStream.put('\n');
  OutStream.flush();
  return OutStream;
}

Iostreams machinery kicks in because it has an ostream& std::operator <<(ostream &(*)(ostream&)) which will provide a match for endl. And of course, you can call endl directly. In other words, these two statements are equivalent:

endl(cout);
cout << endl;

Actually, they are not exactly the same, however their observable semantics is.

There are other standard manipulators. We leave it as an exercise to the reader to research how to create your own manipulator, or how to override something like endl.

posted @ 2013-03-11 23:32  Mr.Shadow  阅读(240)  评论(0编辑  收藏  举报