Difference endl and \n

Well, the title basically tells it all. What is the difference between \n and endl, from what I learn, they both clear and start a new line. But what is the difference? Why not just use \n, as it doesn't require the 'include' or 'using'?
closed account (zb0S216C)
They are two completely different types: '\n' is a character constant, and std::endl() is a function.
The most efficient is the new-line character constant. std::endl() does two things secretly:

- Appends a new-line character to the out-put stream
- Flushes the stream after adding the new-line character

Flushing, in terms of performance, is expensive, and should be used occasionally, but not too often. You can manually flush the stream with a call to std::cout.flush().

Wazzak
Last edited on
In addition to Wazzak's correct answer, the std::cout stream is "secretly" (it's all well documented) flushed right before every input from std::cin and before every output to std::cerr, and at program termination. Flush also happens when the output buffer is full, and, in addition, many systems flush the screen output on every \n even without an explicit request.
About the only time a screen flush is needed in beginner code is after the last output before a long calculation or before a Sleep(), system("pause"), or similar function call.
In my Visual Studio 2010 setup, std::endl is defined in <ostream> (which is included by <iostream>) by this code:
1
2
3
4
5
6
7
8
9
10
		// MANIPULATORS
template<class _Elem,
	class _Traits> inline
	basic_ostream<_Elem, _Traits>&
		__CLRCALL_OR_CDECL endl(basic_ostream<_Elem, _Traits>& _Ostr)
	{	// insert newline and flush stream
	_Ostr.put(_Ostr.widen('\n'));
	_Ostr.flush();
	return (_Ostr);
	}


Put simply, that massive heap of stuff reduces to:
1
2
3
4
5
6
ostream& endl(ostream& o)
{
    o << '\n';
    o << std::flush;
    return o;
}


So really, endl is just a function call that accepts an ostream object such as cout (well, really just traits of an ostream object) and returns the ostream object. So why does this work when we try and insert it into an ostream object? Let's look at how ostream objects accept this type of input:
My Visual Studio 2010 has this in <ostream>:
1
2
3
4
5
	_Myt& __CLR_OR_THIS_CALL operator<<(_Myt& (__cdecl *_Pfn)(_Myt&))
		{	// call basic_ostream manipulator
		_DEBUG_POINTER(_Pfn);
		return ((*_Pfn)(*this));
		}


This reduces to something resembling:
1
2
3
4
ostream& operator<<(ostream& o, ostream& (*manip)(ostream &))
{
    return manip(o);
}


This is a function which overloads the << operator. So if it gets a ostream manipulating function pointer on the right, it will simply call that function and use the ostream object as the argument. Then it will return the ostream object which is also returned by the manip function.
Last edited on
If you're interested, I once made an object (class logger) that was intended to write to cout and an ofstream object at the same time. I had to find a way to overload the << operator so that it would accept any of the standard iomanip objects.

Here are the headers:
1
2
3
4
5
template<class T>   logger& operator<<(const T& output);	   // Accepts chars/strings/doubles/ints/etc.
template<class Arg> logger& operator<<(std::_Smanip<Arg> Smanip);  // Overloaded for parameterized manipulators (setw, setprecision, setiosflags, setbase, resetiosflags)
template<class Arg> logger& operator<<(std::_Fillobj<Arg> Fillobj);// Overloaded for parameterized manipulator setfill
logger& operator<<(std::ostream&  (*manip)(std::ostream &));	   // Overloaded for Output manipulators
logger& operator<<(std::ios_base& (*manip)(std::ios_base&));	   // Overloaded for Basic format flags 


And here are the functions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// This function is the core handler of messages, sending them to files or console and adding system tags
template<class T> // Overloaded for most basic types (int, double, strings, etc.)
logger& logger::operator<<(const T& output) 
{
	std::cout << output;
	fout << output;
	return *this;	// Returns log so that the operator can be used several times in the same line 
}

template <class Arg> // Overloaded for parameterized manipulators
logger& logger::operator<<(std::_Smanip<Arg> Smanip)  // setw(), setprecision(), setbase(), setiosflags() and resetiosflags()
{ 
	(*Smanip._Pfun)(std::cout, Smanip._Manarg);
	(*Smanip._Pfun)(fout     , Smanip._Manarg);
	return *this;
}

template <class Arg>
logger& logger::operator<<(std::_Fillobj<Arg> Fillobj)	// Overloaded for parameterized manipulator setfill()
{
	std::cout.fill(Fillobj._Fill);
	fout.fill     (Fillobj._Fill);
	return *this;
}

logger& logger::operator<<(std::ostream& (*manip)(std::ostream &)) 
{
	manip(std::cout);
	manip(fout);
	return *this;
}

logger& logger::operator<<(std::ios_base& (*manip)(std::ios_base&)) 
{
	manip(std::cout);
	manip(fout);
	return *this;
}


fout is defined as ofstream fout; and the first function actually takes care of some of the other cases so it can be reduced a bit, but I like to keep them all there because it clear how some things are done.
Last edited on
Topic archived. No new replies allowed.