C ++: “std :: endl” vs “\ n”

De nombreux livres en 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 la part de développeurs comme celui-ci:

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

Y a-t-il une raison technique de préférer l’un à l’autre ou est-ce juste une question de style de codage?

Les différents caractères de fin de ligne n’ont aucune importance, en supposant que le fichier est ouvert en mode texte, ce qui est ce que vous obtenez à moins que vous ne demandiez un fichier binary. Le programme compilé va écrire la bonne chose pour le système compilé pour.

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

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 voulez forcer un vidage immédiat à la sortie.
  • Utilisez \n si vous êtes inquiet au sujet des 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 c'est juste une habitude et généralement pas nécessaire).

Contrairement à d'autres affirmations, le caractère \n n'est mappé à la séquence de fin de ligne de plate-forme correcte que si le stream va dans un fichier ( std::cin et std::cout étant des fichiers spéciaux mais fixes (ou de type fichier)) .

Il pourrait y avoir des problèmes de performance, std::endl force un vidage du stream de sortie.

Il y a un autre appel de fonction impliqué si vous voulez 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.

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

Voir la norme C11 qui définit le comportement des stream standard, car les programmes C ++ interfacent le CRT, le standard C11 devant régir la politique de vidage ici.

ISO / IEC 9899: 201x

7.21.3 §7

Au démarrage du programme, trois stream 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 écrire une sortie conventionnelle) et erreur standard (pour écrire une sortie de diagnostic). Comme initialement ouvert, le stream d’erreur standard n’est pas entièrement mis en mémoire tampon; les stream d’entrée standard et les stream de sortie standard sont entièrement tamponnés si et seulement si le stream peut être déterminé pour ne pas se référer à un périphérique interactif.

7.21.3 §3

Lorsqu’un stream est sans tampon, les caractères sont destinés à apparaître depuis la source ou à la destination dès que possible. Sinon, les caractères peuvent être accumulés et transmis vers ou depuis l’environnement hôte en tant que bloc. Lorsqu’un stream est entièrement mis en mémoire tampon, les caractères sont destinés à être transmis à ou depuis l’environnement hôte en tant que bloc lorsqu’un tampon est rempli. Lorsqu’un stream est mis en tampon de ligne, les caractères sont destinés à être transmis à ou depuis l’environnement hôte en tant que bloc lorsqu’un caractère de nouvelle ligne est rencontré. De plus, les caractères sont destinés à être transmis en tant que bloc à l’environnement hôte lorsqu’un tampon est rempli, lorsqu’une entrée est demandée sur un stream sans tampon ou lorsque l’entrée est demandée sur un stream en ligne qui nécessite la transmission de caractères de l’environnement hôte. . La prise en charge de ces caractéristiques est définie par la mise en œuvre et peut être affectée via les fonctions setbuf et setvbuf.

Cela signifie que std::cout et std::cin sont entièrement tamponnés si et seulement s’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 fera pas flush même sur les périphériques interactifs. Sinon, '\n' est équivalent à std::endl sauf si on passe aux fichiers: c ++ ref sur std :: endl .

Ils écrivent tous les deux les caractères de fin de ligne appropriés. En plus de cela, endl provoquera la validation du tampon. Vous ne voulez généralement pas utiliser endl lorsque vous faites des E / S de fichier, car les commits inutiles peuvent avoir un impact sur les performances.

Pas un gros problème, mais endl ne fonctionnera pas dans boost :: lambda .

 (cout<<_1< 

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

 #include  #include  #include  //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 que c'était mon erreur, puisque j'aurais dû écrire std::endl , mais si vous utilisez endl , qt et using namespace std; cela dépend de l'ordre des fichiers d'inclusion si le bon endl sera utilisé. *

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

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

* EDIT2: C ++ choisira la bonne endl si vous using std::cout ou std , puisque std::endl trouve dans le même espace que std::cout , le mécanisme ADL de C ++ choisira std::endl .

J’ai toujours eu l’habitude d’utiliser simplement std :: endl car il est facile pour moi de voir.

Avec référence Il s’agit d’un manipulateur d’E / S à 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édiatement ,

par exemple

lors de l’affichage de la sortie d’un processus de longue durée, l’activité de journalisation de plusieurs threads ou l’activité de journalisation d’un programme qui peut se bloquer de manière inattendue.

Aussi

Un vidage explicite de std :: cout est également nécessaire avant un appel à std :: system, si le processus généré effectue des E / S sur écran. Dans la plupart des autres scénarios d’E / S interactifs, std :: endl est redondant lorsqu’il est utilisé avec std :: cout car toute entrée de std :: cin, sortie en std :: cerr ou terminaison de programme force un appel à 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.

Si vous ne l’avez pas remarqué, endl est comme appuyer sur la touche ENTER alors que "\n" est comme appuyer sur la touche ENTER + SPACE BAR.