IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

std::endl vs '\n'


Sujet :

C++

  1. #1
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut std::endl vs '\n'
    Citation Envoyé par grim7reaper Voir le message
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
     
    int main()
    {
        int a, b;
     
        std::cout << "Saisir deux nombres\n";
        std::cin >> a >> b;
        std::swap(a, b);
        std::cout << a << ' ' << b << '\n';
     
        return 0;
    }
    <mode:chipotage>
    Préférer l'utilisation de std::endl à la place du '\n'.
    </mode>

  2. #2
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    Citation Envoyé par r0d Voir le message
    <mode:chipotage>
    Préférer l'utilisation de std::endl à la place du '\n'.
    </mode>
    Au contraire, j’ai utilisé \n parce que je voulais éviter std::endl. Ici je veux juste faire un retour à la ligne, ni plus ni moins, donc \n est parfaitement adapté.
    Sur stdout, en général std::endl et \n ont le même effet (vu que, par défaut, stdout est souvent bufferisé par ligne) donc oui c’est vraiment une histoire de préférence personnelle que d’utiliser l’un ou l’autre.
    En revanche, sur un fichier on risque de sentir une différence (flusher le buffer à chaque ligne c’est pas terrible niveau perf’ )

  3. #3
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Ma remarque était dans le cadre d'une réponse à une question de débutant. Les deux méthodes étant à peu près identiques, il est conseillé d'utiliser la méthode la plus standard, à savoir celle qui utilise la lib standard du c++.

    Citation Envoyé par grim7reaper Voir le message
    En revanche, sur un fichier on risque de sentir une différence (flusher le buffer à chaque ligne c’est pas terrible niveau perf’ )
    ça dépend le but recherché. Si tu veux faire un logger ou n'importe quel type d'output que tu souhaites pouvoir vérifier en temps réel, alors tu n'as pas le choix. Et de façon générale, ne pas flusher systématiquement pose de nombreux problèmes de robustesse: il est difficile de contrôler le chemin d'exécution si on ne sait pas où ça flushe. Et il y a le problème du multithreading.
    D'une façon générale, il faut préférer le endl. Et si jamais cela pose des problèmes de performance au runtime, alors la question de remplacer par des '\n' pourra se poser, mais seulement après.

  4. #4
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    Citation Envoyé par r0d Voir le message
    Les deux méthodes étant à peu près identiques, il est conseillé d'utiliser la méthode la plus standard, à savoir celle qui utilise la lib standard du c++.
    '\n' c’est autant du C++ standard que std::endl
    Par contre, les deux ont des sémantiques différentes oui : l’un est le moyen standard de faire un retour à la ligne, l’autre est le moyen standard de faire un retour à la ligne + flush.

    Citation Envoyé par r0d Voir le message
    ça dépend le but recherché. Si tu veux faire un logger ou n'importe quel type d'output que tu souhaites pouvoir vérifier en temps réel, alors tu n'as pas le choix.
    Oui, tout à fait.
    Dans ce cas-là c’est pleinement justifié.

    Citation Envoyé par r0d Voir le message
    Et de façon générale, ne pas flusher systématiquement pose de nombreux problèmes de robustesse: il est difficile de contrôler le chemin d'exécution si on ne sait pas où ça flushe.
    Rien n’empêche de faire des appels à std::flush à des « points de contrôle ». Comme ça tu sais exactement où ça flushe.
    Après tout dépend de l’application (oui un logger doit flusher à chaque ligne donc std::endl est parfait), mais il peut aussi y avoir un juste milieu entre ne jamais flusher (laisser le système gérer) et flusher à chaque ligne.

    Citation Envoyé par r0d Voir le message
    Et il y a le problème du multithreading.
    Hum, en général si tu as plusieurs threads qui veulent écrirent en même temps sur le même flux tu vas protéger l’accès par un mutex, flush ou pas.
    Le flush ne va pas te protéger de l’entrelacement pour ce que j’en sais.

    Citation Envoyé par r0d Voir le message
    D'une façon générale, il faut préférer le endl. Et si jamais cela pose des problèmes de performance au runtime, alors la question de remplacer par des '\n' pourra se poser, mais seulement après.
    Personnellement, j’ai plutôt l’approche inverse.
    Par défaut, on va au plus simple : simple retour à la ligne.
    Après, si besoin il y a ou cas particulier (le logger était un très bon exemple), on ajoute des flush (ou usage de std::endl).

    Mais, ça reste un détail.

  5. #5
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par grim7reaper Voir le message
    '\n' c’est autant du C++ standard que std::endl
    Non, endl prend en compte les différences entre système d'exploitation, les encodages, etc. Par exemple, dans certains encodages, un retour charriot d'un fichier est '\r\n'. endl gère tout ça.

    Citation Envoyé par grim7reaper Voir le message
    Rien n’empêche de faire des appels à std::flush à des « points de contrôle ». Comme ça tu sais exactement où ça flushe.
    Après tout dépend de l’application (oui un logger doit flusher à chaque ligne donc std::endl est parfait), mais il peut aussi y avoir un juste milieu entre ne jamais flusher (laisser le système gérer) et flusher à chaque ligne.

    Hum, en général si tu as plusieurs threads qui veulent écrirent en même temps sur le même flux tu vas protéger l’accès par un mutex, flush ou pas.
    Le flush ne va pas te protéger de l’entrelacement pour ce que j’en sais.
    En gros, pourquoi faire simple quand on peut faire compliqué?
    Pour le MT, utiliser endl te permet au moins de ne protéger que tes accès en écriture. Si tu utilises '\n', il faut que tu gère les accès concurrents à tous les niveaux, ça peut vite devenir ingérable.

    Citation Envoyé par grim7reaper Voir le message
    Par défaut, on va au plus simple : simple retour à la ligne.
    Sauf que le plus simple c'est le endl, c'est pas le '\n'. De même que le plus simple c'est la classe string, pas le char*.

    Citation Envoyé par grim7reaper Voir le message
    Mais, ça reste un détail.
    C'est un détail, mais si cette discussion revient régulièrement c'est parce qu'elle cristallise deux visions du c++. Une vision qui conçoit le c++ en tant qu'amélioration du C, et une autre vision, qui est la mienne, qui prend le c++ comme un langage à part entière, et dont la stl est la brique de base, dont il faut abuser.

  6. #6
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    Citation Envoyé par r0d Voir le message
    Non, endl prend en compte les différences entre système d'exploitation, les encodages, etc. Par exemple, dans certains encodages, un retour charriot d'un fichier est '\r\n'. endl gère tout ça.
    Ça c’est un mythe. \n a exactement le même effet au niveau de l’encodage de la fin de ligne. C’est tout aussi portable.
    Et tu sais pourquoi ?
    Parce std::endl ne fait rien de plus que d’écrire \n dans le flux puis il appelle std::flush. Il y a bien un appel à os.widen mais ça n’a rien à voire avec les histoire de \n, \r ou \r\n…
    Je t’invite à faire le test (ou à lire la section 27.7.3.8 du standard).

    Citation Envoyé par r0d
    En gros, pourquoi faire simple quand on peut faire compliqué?
    Pour le MT, utiliser endl te permet au moins de ne protéger que tes accès en écriture. Si tu utilises '\n', il faut que tu gère les accès concurrents à tous les niveaux, ça peut vite devenir ingérable.
    Là je ne vois pas de quoi tu parles.
    flush ou pas, si deux threads joue en même temps sur le même flux tu risques des soucis.
    Tu peux me donner un exemple s’il te plaît ? Ça sera peut-être plus clair.

    Citation Envoyé par r0d
    Sauf que le plus simple c'est le endl, c'est pas le '\n'. De même que le plus simple c'est la classe string, pas le char*.
    Je suis d‘accord pour std::string vs char*, par contre pas pour std::endl vs \n.
    Pour moi il n’est pas plus simple, il joue un autre rôle.

    Citation Envoyé par r0d
    C'est un détail, mais si cette discussion revient régulièrement c'est parce qu'elle cristallise deux visions du c++. Une vision qui conçoit le c++ en tant qu'amélioration du C, et une autre vision, qui est la mienne, qui prend le c++ comme un langage à part entière, et dont la stl est la brique de base, dont il faut abuser.
    Moi aussi j’ai cette vision et je lutte contre ceux qui font du C-with-classes ou un sabir C/C++.
    Mais là, à t’entendre on dirait que \n ce n’est pas du C++, mais du C. Et je trouve ça un peu fort.
    Moi aussi je suis pour utiliser à fond la STL, quand c’est justifié. Mais je pense aussi que quand \n remplit son rôle autant l’utiliser (surtout qu’il est tout aussi portable que std::endl comme je l’ai montré plus haut).

  7. #7
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par grim7reaper Voir le message
    Ça c’est un mythe. \n a exactement le même effet au niveau de l’encodage de la fin de ligne. C’est tout aussi portable.
    Et tu sais pourquoi ?
    Parce std::endl ne fait rien de plus que d’écrire \n dans le flux puis il appelle std::flush. Il y a bien un appel à os.widen mais ça n’a rien à voire avec les histoire de \n, \r ou \r\n…
    Je t’invite à faire le test (ou à lire la section 27.7.3.8 du standard).
    Je n'ai malheureusement pas la norme sous la main. Et peut-être que cette histoire de '\r\n' est un mythe, mais je sais que j'ai eu des soucis avec ça quand j'étais débutant. Bon à l'époque je ne comprenais pas grand chose au c++, alors j'ai sans doute mal compris le problème. Mais quoi qu'il en soit, comme tu l'as noté, il y a cet appel à widen qui normalise l'encodage.

    Citation Envoyé par grim7reaper Voir le message
    Là je ne vois pas de quoi tu parles.
    flush ou pas, si deux threads joue en même temps sur le même flux tu risques des soucis.
    Tu peux me donner un exemple s’il te plaît ? Ça sera peut-être plus clair.
    Je ne trouve pas d'exemple, tu as peut-être raison en fait.
    Mais si on oublie le MT, il me parait tout de même nettement plus compliqué de chercher les endroits corrects pour flusher son buffer, sans parler des problèmes potentiels de maintenance, plutôt que de le faire systématiquement.

    Citation Envoyé par grim7reaper Voir le message
    Mais là, à t’entendre on dirait que \n ce n’est pas du C++, mais du C. Et je trouve ça un peu fort.
    Je l'ai dit de façon un peu abrupte, et je m'en excuse, mais ce que je veux dire, c'est que dans 99% des cas, les quelques cycles qu'on va gagner en n'utilisant pas la STL n'en valent pas la peine. Par exemple, si tu veux faire un tableau de 3 entiers, tu vas gagner probablement quelques cycles en utilisant un int[3] plutôt qu'un vector<int> (et encore c'est pas sûr), mais dans 99% des cas, ce gain de perf est dérisoire et même si la performance est une contrainte critique (ce qui est assez rare dans la vrai vie), cette différence n'apparaitra même pas au profiling.

  8. #8
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    Citation Envoyé par r0d Voir le message
    Je n'ai malheureusement pas la norme sous la main. Et peut-être que cette histoire de '\r\n' est un mythe, mais je sais que j'ai eu des soucis avec ça quand j'étais débutant. Bon à l'époque je ne comprenais pas grand chose au c++, alors j'ai sans doute mal compris le problème. Mais quoi qu'il en soit, comme tu l'as noté, il y a cet appel à widen qui normalise l'encodage.
    En fait, tant que que le flux est en mode texte, le \n est interprété comme il faut pour la plateforme sous-jacente.

    Par contre, c’est vrai que l’on profite automatiquement du widen en utilisant std::endl.
    Cela dit, je ne sais pas si on y gagne tant que ça, car de toutes façons pour écrire autre chose que de l’ASCII il faut passer par std::wcout (donc un changement explicite à faire) il me semble, donc std::endl ne fait pas tout. Mais oui, sur ce coup-là c’est plus pratique qu’un \n nu, c’est vrai.

    Citation Envoyé par r0d Voir le message
    Mais si on oublie le MT, il me parait tout de même nettement plus compliqué de chercher les endroits corrects pour flusher son buffer, sans parler des problèmes potentiels de maintenance, plutôt que de le faire systématiquement.
    Oui, si on veut flusher c’est plus simple de le faire partout qu’au cas pas cas. C’est sûr.
    Mais j’ai vraiment vu de nombreux témoignages sur le fait que utiliser std::endl de manière systématique lorsque l’on bosse avec un fichier diminuait les performances de manière non négligeable (un facteur 2 ou plus n’étant pas rare, sauf si c’est pour écrire 4 lignes bien sûr).
    Bon, après peut-être que ces témoignages datent un peu et que maintenant c’est beaucoup moins pénalisant. Dans tout les cas c’est à voir au cas pas cas, selon l’application (contrainte de vitesse, robustesse, etc.). Pas de règle absolue.

    Citation Envoyé par r0d
    Je l'ai dit de façon un peu abrupte, et je m'en excuse, mais ce que je veux dire, c'est que dans 99% des cas, les quelques cycles qu'on va gagner en n'utilisant pas la STL n'en valent pas la peine.
    Tout à fait d’accord.
    Et on gagne toujours plus à optimiser son algorithme qu’a remplacer des std::string par des char* (et je ne parle même pas de la clarté du code, du risque de bug en moins et du temps gagné en développement).

    Citation Envoyé par r0d
    Par exemple, si tu veux faire un tableau de 3 entiers, tu vas gagner probablement quelques cycles en utilisant un int[3] plutôt qu'un vector<int> (et encore c'est pas sûr), mais dans 99% des cas, ce gain de perf est dérisoire et même si la performance est une contrainte critique (ce qui est assez rare dans la vrai vie), cette différence n'apparaitra même pas au profiling.
    Et puis depuis le C++11, avec std::array ce n’est même pas sûr que l’on y gagne encore quoique ce soit
    Mais je suis d’accord avec ton exemple.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 146
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    j'ai splité les messages depuis la discussion d'origine.
    Inutile de géner un débutant avec de tels considérations, vous pouvez continuer votre débat/battle (débattle ?!) ici
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Yep, t'as raison Bousk, on va faire fuir nos débutants avec ces trolls débats sans fin
    Mais je reste convaincu qu'il vaut mieux enseigner aux débutants d'utiliser systématiquement endl à la place de '\n'.
    Non, je lâche rien!

  11. #11
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    Le découpage est le bienvenue.
    C’est vrai que l’on commençait à être sérieusement HS ^^"

    Citation Envoyé par r0d Voir le message
    Yep, t'as raison Bousk, on va faire fuir nos débutants avec ces trolls débats sans fin
    Mais je reste convaincu qu'il vaut mieux enseigner aux débutants d'utiliser systématiquement endl à la place de '\n'.
    Non, je lâche rien!
    Moi je pense qu’il faut leur enseigner les deux, pour qu’ensuite ils puissent choisir en connaissance de cause.
    Personnellement le trouve l’entrée de la FAQ plutôt bien faire : elle est courte (pas comme nos messages à rallong qui effraie les débutants ) et explique la différence.
    Après, une fois informé chacun prend sa décision en connaissance de cause.

  12. #12
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,
    Citation Envoyé par grim7reaper Voir le message
    Le découpage est le bienvenue.
    C’est vrai que l’on commençait à être sérieusement HS ^^"


    Moi je pense qu’il faut leur enseigner les deux, pour qu’ensuite ils puissent choisir en connaissance de cause.
    J'ai toujours eu pour principe d'avoir, dans l'ordre:
    1. un code compréhensible par celui qui pose les yeux dessus
    2. un code qui fait ce qu'on lui demande
    3. un code qui fait rapidement ce qu'on lui demande
    Si je mets les choses dans cet ordre, c'est parce qu'il est beaucoup plus facile, au niveau de la maintenance de corriger un code bien écrit, surtout s'il est lent qu'un code qui arrive rapidement au plantage

    Et, personnellement, j'ai tendance à estimer qu'il est "si facile" de passer à coté d'un '\n', surtout s'il est bien encadré, que std::endl a, au moins, le mérite d'être beaucoup plus visible.

    D'autant plus que, je ne sais pas vous, mais, d'habitude, je vais à la ligne (au niveau du code) après std::endl, plus rarement après un '\n'

    Enfin, je crois qu'avant de commencer à s'inquiéter d'un flush peut etre intempestif, il y a le plus souvent énormément à faire au niveau des algorithmes et de la logique en générale et que, une fois que ce travail là est fait, il y a très certainement d'autres moyens à aborder, comme le fait d'éviter les cache miss, avant de s'inquiéter de savoir si l'on gagne deux cycles en utilisant '\n'.

    Je ne vais pas rentrer d'avantage dans le débat, car je suis sur ce coup en total accord avec r0d, mais je tenais malgré tout à vous faire profiter de mon opinion personnelle... mais que je partage
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #13
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    La dernière version de C++ Primer conseille effectivement d'utiliser \n dans le cas d'une écriture vers des fichiers.

    Par ailleurs, selon moi, les tableaux ne doivent être remplacés par des vecteurs que si la taille n'est pas connue à la compilation.

  14. #14
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Et, personnellement, j'ai tendance à estimer qu'il est "si facile" de passer à coté d'un '\n', surtout s'il est bien encadré, que std::endl a, au moins, le mérite d'être beaucoup plus visible.

    D'autant plus que, je ne sais pas vous, mais, d'habitude, je vais à la ligne (au niveau du code) après std::endl, plus rarement après un '\n'
    Ces défauts dépendent de comment tu présentes ton code.
    Après, je ne cherche pas à imposer l’usage de \n partout au lieu de std::endl.
    Pour moi ce sont juste deux choses différentes qui ont des usages différents (mais proche), du coup personnellement je me pose rarement la question d’utiliser l’un ou l’autre car les cas d’usage sont différents (comme puts et printf en C).

    Citation Envoyé par koala01 Voir le message
    si l'on gagne deux cycles en utilisant '\n'.
    Sur un truc un avec des I/O un tant soit peu conséquente, il y’a bien plus de 2 cycles à gagner entre un flush à chaque ligne ou pas…
    Un flush ça implique un accès disque ce qui est très lent, la bufferisation permet d’écrire en RAM et de grouper les accès disque donc forcément l’écart n’est pas que de deux cycles (ou alors c’est encore mieux qu’un SSD ce que tu as ).

    Mis à part ce détail, je suis totalement d’accord que l’on a plus à gagner en soignant les algorithmes et la logique de haut niveau. C’est certain (je le disais d’ailleurs dans un message précédent).
    Mais j’ai l’impression que tu sous-estime quand même un peu le coût d’un flush. Pour moi c’est de même niveau que les caches miss (après je ne connais pas les rapports temps d’accès cache/RAM et RAM/disque), si ce n’est que c’est moins fréquent (les flush ne concernent que les I/O, les cache miss c’est plus global donc oui il vaut mieux les optimiser en premier).

    Citation Envoyé par oodini Voir le message
    Par ailleurs, selon moi, les tableaux ne doivent être remplacés par des vecteurs que si la taille n'est pas connue à la compilation.
    Oui, sinon il vaut mieux utiliser les std::array (C++11) ou std::dynarray (C++14)

  15. #15
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 287
    Par défaut
    Je suis derrière grim7reaper sur l'histoire.

    - endl ne protège en rien contre les accès concurrents. Mais alors rien du tout. cout est une variable globale, et les << de chaque thread peuvent s'entrelacer (et même à l'intérieur du code des <<, il peut y avoir des entrelacements). Pour s'en sortir, il faut remplacer le streambuf de cout par un streambuf qui contient un ensemble de streambufs (un par thread ; par TLS/TSS ou autre moyen), et flusher le streambuf du thread courant sur un flush.

    - endl, ce n'est jamais que \n + flush (sur cout, sur wcout, bien évidemment, c'est autre chose, mais vu que la chaine littérale que l'on écrit sera adaptée, le \n aussi, IIRC)

    - et \n en mode non binaire sera adapté en ce qui va bien pour le couple OS/compilo


    Quand à mon code, je préfère aujourd'hui employer \n qui est bien plus concis, et tout aussi clair pour tout ceux qui font du C, du bash, du perl, ...
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  16. #16
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par grim7reaper Voir le message
    Sur un truc un avec des I/O un tant soit peu conséquente, il y’a bien plus de 2 cycles à gagner entre un flush à chaque ligne ou pas…
    Un flush ça implique un accès disque ce qui est très lent, la bufferisation permet d’écrire en RAM et de grouper les accès disque donc forcément l’écart n’est pas que de deux cycles (ou alors c’est encore mieux qu’un SSD ce que tu as ).
    Après un rapide test : écriture d'~1 millions de lignes (2^20) dans un fichier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // lignes de 1 caractère (3Mo au total)
    std::endl 1413.08ms
    '\n': 111.006ms
     
    // lignes de 1024 caractères (~1Go au total)
    std::endl 4084.23ms
    '\n': 3018.17ms
    Ça donne une idée (au moins un ordre de grandeur) du coût de std::endl.

  17. #17
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    @lmghs: il me semble justement que pour les buffers synchronisés (comme std::cout), chaque << doit être thread-safe d'après ce que j'en lis sur cppreference, et atomique de ce que j'ai pu observer de mes nombreux tests :
    Citation Envoyé par cppreference
    Unless sync_with_stdio(false) has been issued, it is safe to concurrently access these objects from multiple threads for both formatted and unformatted output.

  18. #18
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    C’est garanti, oui tu raison :
    Citation Envoyé par ISO/IEC N3242 §27.4.14
    Concurrent access to a synchronized (27.5.3.4) standard iostream object’s formatted and unformatted input (27.7.2.1) and output (27.7.3.1) functions or a standard C stream by multiple threads shall not result in a data race (1.10). [ Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. — end note ]
    Mais comme précisé, il y a toujours besoin de synchro’ pour éviter l’entrelacement.
    Du coup, std::endl n’aide absolument en rien à ce niveau-là.

  19. #19
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 287
    Par défaut
    Au temps pour moi alors.

    BTW, tu peux dire Luc ici
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  20. #20
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    Oups, l'habitude .

    Même si ce n'est pas garanti par le standard visiblement (d'après la note ?), je n'ai jamais eu d'entrelacement de caractères :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //thread1
    std::cout << "bonjour" << "bonsoir";
     
    //thread2
    std::cout << "ohayo" << "konbanwa";
    Peut donner :
    bonjourohayobonsoirkonbanwa
    Mais pas plus mélangé que ça.

Discussions similaires

  1. faire comme std::endl
    Par mister3957 dans le forum C++
    Réponses: 4
    Dernier message: 21/01/2010, 14h03
  2. surcharger std::endl ?
    Par ambroise_petitgenet dans le forum SL & STL
    Réponses: 2
    Dernier message: 28/03/2009, 14h47
  3. Surcharge d'opérateur << et std::endl;
    Par Tourix dans le forum SL & STL
    Réponses: 7
    Dernier message: 29/06/2006, 17h58
  4. std::endl c'est quoi ??
    Par elekis dans le forum SL & STL
    Réponses: 8
    Dernier message: 14/09/2005, 17h15
  5. STL : std::set problème avec insert ...
    Par Big K. dans le forum MFC
    Réponses: 13
    Dernier message: 08/11/2003, 01h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo