web-dev-qa-db-fra.com

C++: "std :: endl" vs "\ n"

De nombreux livres C++ contiennent un exemple de code comme celui-ci ...

std::cout << "Test line" << std::endl;

... donc j'ai toujours fait ça aussi. Mais j'ai vu beaucoup de code de développeurs travaillant comme ceci:

std::cout << "Test line\n";

Existe-t-il une raison technique pour préférer l'une ou l'autre, ou s'agit-il simplement d'un style de codage?

480
Head Geek

Les différents caractères de fin de ligne importent peu, en supposant que le fichier soit ouvert en mode texte, ce que vous obtiendrez à moins que vous ne demandiez du binaire. Le programme compilé écrira ce qui convient pour le système compilé.

La seule différence est que std::endl vide le tampon de sortie et que '\n' ne le fait pas. Si vous ne voulez pas que le tampon soit vidé fréquemment, utilisez '\n'. Si vous le faites (par exemple, si vous souhaitez obtenir toutes les sorties et que le programme est instable), utilisez std::endl.

410
David Thornley

La différence peut être illustrée par ce qui suit:

std::cout << std::endl;

est équivalent à

std::cout << '\n' << std::flush;

Alors,

  • Utilisez std::endl Si vous souhaitez forcer un vidage immédiat vers la sortie.
  • Utilisez \n si vous êtes préoccupé par les performances (ce qui n'est probablement pas le cas si vous utilisez l'opérateur <<).

J'utilise \n sur la plupart des lignes.
Ensuite, utilisez std::endl à la fin d'un paragraphe (mais ce n'est qu'une habitude et n'est généralement pas nécessaire).

Contrairement à d'autres affirmations, le caractère \n est associé à la séquence de fin de ligne de la plate-forme correcte uniquement si le flux est dirigé vers un fichier (std::cin et std::cout étant des fichiers spéciaux mais toujours des fichiers (ou des fichiers similaires)).

205
Martin York

Il peut y avoir des problèmes de performances, std::endl force le vidage du flux de sortie.

40
Martin Beckett

Je me suis rappelé avoir lu à ce sujet dans la norme, alors voici:

Voir la norme C11 qui définit le comportement des flux standard, car les programmes C++ interfacent le tube cathodique. La norme C11 devrait donc régir la politique de vidage.

ISO/IEC 9899: 201x

7.21.3 §7

Au démarrage du programme, trois flux de texte sont prédéfinis et n'ont pas besoin d'être ouverts explicitement - entrée standard (pour lire une entrée conventionnelle), sortie standard (pour écriture Sortie conventionnelle) et erreur standard (pour écriture d'une sortie de diagnostic). Comme initialement ouvert, le flux d'erreur standard n'est pas entièrement mis en mémoire tampon; l'entrée standard et standard les flux de sortie sont entièrement mis en mémoire tampon si et seulement si le flux peut être déterminé de ne pas faire référence à un appareil interactif.

7.21.3 §3

Lorsqu'un flux n'est pas mis en mémoire tampon, les caractères doivent apparaître à partir de la source ou au niveau destination le plus tôt possible. Sinon, les caractères peuvent être accumulés et transmis à ou de l'environnement hôte en tant que bloc. Lorsqu'un flux est entièrement mis en mémoire tampon, Les caractères sont destinés à être transmis vers ou depuis l'environnement hôte sous forme de bloc lorsque un tampon est rempli. Lorsqu'un flux est mis en mémoire tampon, les caractères doivent être transmis à ou de l'environnement hôte sous forme de bloc lorsqu'un caractère de nouvelle ligne est rencontré. De plus, les caractères sont destinés à être transmis en bloc à l'hôte environnement quand un tampon est rempli, quand l'entrée est demandée sur un flux sans tampon, ou lorsqu'une entrée est demandée sur un flux de ligne mis en mémoire tampon qui nécessite la transmission de personnages de l'environnement hôte. Le support pour ces caractéristiques est défini par la mise en œuvre, et peut être affecté via les fonctions setbuf et setvbuf.

Cela signifie que std::cout et std::cin sont entièrement mis en mémoire tampon si et seulement si ils font référence à un périphérique non interactif. En d'autres termes, si stdout est attaché à un terminal, il n'y a pas de différence de comportement. 

Cependant, si std::cout.sync_with_stdio(false) est appelé, alors '\n' ne provoquera pas de vidage, même pour les périphériques interactifs. Sinon, '\n' équivaut à std::endl sauf si la tuyauterie dans les fichiers: c ++ ref sur std :: endl .

24
Emily L.

Il y a un autre appel de fonction impliqué si vous allez utiliser std::endl

a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

a) appelle l'opérateur << une fois. 
b) appelle l'opérateur << deux fois.

23
Nathan

Ils écriront tous les deux les caractères de fin de ligne appropriés. En plus de cela, endl entraînera la validation de la mémoire tampon. En règle générale, vous ne souhaitez pas utiliser endl lorsque vous effectuez des E/S sur un fichier, car les validations inutiles peuvent affecter les performances.

18
Ferruccio

Ce n'est pas grave, mais endl ne fonctionnera pas dans boost :: lambda .

(cout<<_1<<endl)(3); //error

(cout<<_1<<"\n")(3); //OK , prints 3
11
Özgür

Si vous utilisez Qt et endl, vous pourriez accidentellement utiliser le mauvais endl, m'est arrivé aujourd'hui et j'étais comme ..WTF ??

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>
//notice that i dont have a "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution !" << endl << "...";
    // Line above printed: "Finished Execution !67006AB4..."
    return qapp.exec();
}

Bien sûr, c'était mon erreur, car j'aurais dû écrire std::endlmais si vous utilisez endl, qt et using namespace std;, cela dépend de l'ordre des fichiers d'inclusion si la endl correcte sera utilisée.*

Bien sûr, vous pouvez recompiler Qt pour utiliser un espace de noms. Vous obtenez donc une erreur de compilation pour l'exemple ci-dessus.

EDIT: Oublié de mentionner, la variable endl de Qt est déclarée dans "qtextstream.h" qui fait partie de QtCore

* EDIT2: C++ choisira la endl correcte si vous avez une using pour std::cout ou un espace de noms std, puisque std::endl est dans le même espace de noms que std::cout, le mécanisme ADL de C++ choisira std::endl.

9
smerlin

J'ai toujours eu l'habitude d'utiliser simplement std :: endl car c'est facile à voir pour moi.

2
Zee JollyRoger

With reference Ceci est un manipulateur d'E/S en sortie uniquement.

std::endl Insère un caractère de nouvelle ligne dans la séquence de sortie os et le vide comme s'il appelait os.put(os.widen('\n')) suivi de os.flush()

Quand utiliser:

Ce manipulateur peut être utilisé pour produire une ligne de sortie immédiate

par exemple. 

lors de l'affichage de la sortie d'un processus de longue durée, de la journalisation de l'activité de plusieurs threads ou de la journalisation d'un programme susceptible de planter de manière inattendue. 

Également

Un vidage explicite de std :: cout est également nécessaire avant un appel à std :: system, si le processus engendré effectue une opération d’écran d’écran. Dans la plupart des autres scénarios d’E/S interactifs habituels, std :: endl est redondant s’il est utilisé avec std :: cout, car toute entrée de std :: cin, la sortie vers std :: cerr ou la terminaison de programme force un appel vers std :: cout. .affleurer(). L'utilisation de std :: endl à la place de '\ n', encouragée par certaines sources, peut dégrader considérablement les performances de sortie. 

1
Kaleem Ullah

Si vous avez l'intention d'exécuter votre programme sur autre chose que votre propre ordinateur portable, n'utilisez jamais l'instruction endl. Surtout si vous écrivez beaucoup de lignes courtes ou que j'ai souvent vu des caractères uniques dans un fichier. L'utilisation de endl est connue pour tuer les systèmes de fichiers en réseau tels que NFS.

0

Le manipulateur endl est équivalent à '\'. Mais endl vide toujours le flux.

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush
0
crl7