De um ponto de vista simplista:
std::cout << std::endl;
// é equivalente a
std::cout << "\n" << std::flush;
Claro que quem estiver usando o operador '<<' deve saber que operações de I/O, mesmo bufferizadas, são operações lentas. Então não leve o assunto performace TÃO a sério nesse cenário. Em contra partida lembre que o flush pode criar algumas chamadas a mais e se o seu código é uma classe de log em arquivo no disco, por exemplo, então você pode ter uma perda de performace SIM. Vale lembrar que isso acontece pois, no geral, escrever um bloco de bytes é mais economico do que escrever varios bytes um de cada vez, os dispositivos são desenhados para efetuar operações com multiplos bytes então aproveite essa feature! E lembre-se que no geral, para arquivos abertos em modo texto, o newline será mapeado para o caracter correto de fim de linha(LF em Unix, CRLF no DOS(Windows), CR no Macintosh, e por ai vai), vale lembrar que cout e cin são arquivos especiais, ou uma especie de arquivo(se você prefere assim) e também vão se comportar como tal. Para não manter o artigo tão superficial vamos olhar a implementação do endl na libstdc++ da GNU:
/**
* @brief Write a newline and flush the stream.
*
* This manipulator is often mistakenly used when a simple newline is
* desired, leading to poor buffering performance. See
* http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#2 for more
* on this subject.
*/
template
basic_ostream<_CharT, _Traits>& endl(basic_ostream<_CharT, _Traits>& __os)
{
return flush(__os.put(__os.widen('\n')));
}
Veja que a documentação é bem clara quanto ao comportamento do endl, mas olhando o código fica claro o que acontece. O endl recebe o stream que vai operar como parâmetro e chama o put para inserir um '\n'. O retorno do put será enviado para o flush causando, obviamente, um flush na stream.
That's all!!!