endl et rinçage du tampon
Dans le livre C++ primer , au chapitre (1), il mentionne ce qui suit:
Endl est une valeur spéciale, appelée manipulateur, qui, lorsqu'elle est écrite dans un le flux de sortie a pour effet d'écrire une nouvelle ligne dans la sortie et vider le tampon associé à ce périphérique. en vidant le tampon, nous nous assurons que l'utilisateur verra la sortie écrite dans le diffusez immédiatement.
Qu'entend-on par" vider le tampon " ici?
5 réponses
La sortie est généralement mise en mémoire tampon avant d'être écrite sur le périphérique prévu. De cette façon, lors de l'écriture pour ralentir pour accéder aux périphériques(comme les fichiers), il n'a pas besoin d'accéder à l'appareil après chaque caractère.
Le rinçage signifie vider le tampon et l'écrire réellement sur le périphérique.
Les iostreams de C++sont mis en mémoire tampon, ce qui signifie que lorsque vous produisez dans un ostream, le contenu n'ira pas immédiatement à ce qui se trouve derrière le flux, par exemple stdout dans le cas de cout. L'implémentation du flux détermine quand envoyer réellement la partie tamponnée du flux. Ceci est fait pour des raisons d'efficacité, il serait très inefficace d'écrire sur un réseau ou un flux de disque octet par octet, en mettant en mémoire tampon ce problème est résolu.
Cela signifie cependant que lorsque vous écrivez dites messages de débogage dans un fichier journal et votre programme se bloque vous risquez de perdre une partie des données que vous avez écrites dans le fichier journal à travers le flux, car une partie du journal peut toujours être dans le tampon du flux et pas encore écrit dans le fichier réel. Pour éviter que cela ne se produise, vous devez vider le flux de ses tampons soit par un appel de méthode de vidage explicite, soit en utilisant la commodité de endl.
Si toutefois vous écrivez simplement dans un fichier régulièrement, vous devez utiliser \n au lieu de endl pour empêcher le flux de vider inutilement le flux chaque ligne réduisant vos performances.
Modifié pour inclure cette note:
Cin et cout ont une relation spéciale, où la lecture de cin videra automatiquement cout au préalable. Cela garantit que l'invite que vous avez écrite à cout sera réellement vue par l'utilisateur avant que la lecture de cin n'attende l'entrée. Par conséquent, même dans cout, vous n'avez normalement pas besoin de endl mais pouvez utiliser \n à la place. Vous pouvez créer de telles relations entre d'autres flux aussi bien en les liant ensemble.
Qu'entend-on par "vider le tampon" ici?
std::endl
provoque le "vidage" (transfert) des données de la mémoire intermédiaire interne du flux (son "tampon") vers le système d'exploitation. Le comportement suivant dépend du type de périphérique auquel le flux est mappé, mais en général, le vidage donne l'impression que les données ont été physiquement transférées vers le périphérique associé. Une perte soudaine de puissance, cependant, pourrait vaincre l'illusion.
Ce le rinçage implique un certain overhead (Temps Perdu), et devrait donc être minimisé lorsque la vitesse d'exécution est une préoccupation importante. Minimiser l'impact global de ces frais généraux est l'objectif fondamental de mise en mémoire tampon des données, mais cet objectif peut être vaincu par un rinçage excessif.
Informations générales
Les e/s d'un système informatique sont généralement très sophistiquées et composées de plusieurs couches d'abstraction. Chaque couche peut introduire une certaine quantité de frais généraux. La mise en mémoire tampon des données est un moyen de réduire cette surcharge en minimisant le nombre de transactions individuelles effectuées entre deux couches du système.
Mise en mémoire tampon au niveau du système CPU/Mémoire (caching) : pour une activité très élevée, même le système de mémoire à accès aléatoire d'un ordinateur peut devenir un goulot d'étranglement. Pour résoudre ce problème, le processeur virtualise les accès à la mémoire en fournissant plusieurs couches de caches cachés (les tampons individuels de qui sont appelées lignes de cache). Ces caches de processeur tamponnent les Écritures de mémoire de votre algorithme (conformément à une politique d'écriture ) afin de minimiser les accès redondants sur le bus mémoire.
Mise en mémoire tampon au niveau de L'Application : bien que ce ne soit pas toujours nécessaire, il n'est pas rare qu'une application alloue des morceaux de mémoire pour accumuler des données de sortie avant de les transmettre à la bibliothèque d'E/S. Cela fournit l'avantage fondamental de permettre des accès aléatoires (si nécessaire), mais une raison importante pour le faire est qu'il minimise la surcharge associée aux appels de bibliothèque - ce qui peut prendre beaucoup plus de temps que d'écrire simplement dans un tableau de mémoire.
Mise en mémoire tampon de la bibliothèque d'E/S: la bibliothèque de flux D'E / S C++ gère éventuellement un tampon pour chaque flux ouvert. Ce tampon est utilisé, en particulier, pour limiter le nombre de appels système au noyau du système d'exploitation parce que de tels appels ont tendance à avoir des frais généraux non triviaux. c'est le tampon qui est vidé lors de l'utilisation de
std::endl
.-
Noyau du système D'exploitation et pilotes de périphérique : le système d'exploitation achemine les données vers un pilote de périphérique spécifique (ou sous-système) en fonction du périphérique de sortie auquel le flux est connecté. À ce stade, le comportement réel peut varier considérablement selon la nature et les caractéristiques de ce type d'appareil. Par exemple, lorsque le périphérique est un disque dur, le pilote de périphérique peut Pas initier un transfert immédiat vers le périphérique, mais plutôt maintenir son propre tampon afin de minimiser davantage les opérations redondantes (puisque les disques, eux aussi, sont plus efficacement écrits en morceaux). Afin de vider explicitement les tampons au niveau du noyau, il peut être nécessaire d'appeler une fonction au niveau du système telle que
fsync() on Linux
-- même fermer le flux associé, ne force pas nécessairement un tel rinçage.Exemple de sortie les périphériques peuvent inclure...
- un terminal sur la machine locale
- un terminal sur une machine distante (via SSH ou similaire)
- les données sont envoyées à une autre application via tuyaux ou prises
- de nombreuses variantes de dispositifs de stockage de masse et de systèmes de fichiers associés, qui peuvent être (encore une fois) connectés localement ou distribués via un réseau
Tampons Matériels: matériel Spécifique peut contenir ses propres tampons de mémoire. Dur les lecteurs, par exemple, contiennent généralement un tampon de disque afin (entre autres) de permettre aux Écritures physiques de se produire sans nécessiter que le processeur du système soit engagé dans l'ensemble du processus.
Dans de nombreuses circonstances, ces différentes couches de tampon ont tendance à être (dans une certaine mesure) redondantes-et donc essentiellement exagérées. Cependant, la mise en mémoire tampon à chaque couche peut fournir un gain de débit énorme si les autres couches, pour quelque raison, ne parviennent pas à fournir une mise en mémoire tampon optimale par rapport à la surcharge associée à chaque couche.
Longue histoire courte, std::endl
seul a adressé le tampon qui est géré par la bibliothèque de flux D'E / S C++ pour ce flux particulier. Après avoir appelé std::endl
, les données auront été déplacées vers la gestion au niveau du noyau, et ce qui se passe ensuite avec les données dépend d'un grand nombre de facteurs.
Comment éviter les frais généraux de std::endl
- Méthode 1: Ne pas utiliser
std::endl
-- Utilisez'\n'
à la place. - Méthode 2: Ne pas utiliser
std::endl
-- utilisez quelque chose comme la version suivante à la place ...
inline std::ostream & endl( std::ostream & os )
{
os.put( os.widen('\n') ); // http://en.cppreference.com/w/cpp/io/manip/endl
if ( debug_mode ) os.flush(); // supply 'debug_mode' however you want
return os;
}
Dans cet exemple, vous fournissez un endl
personnalisé qui peut être appelé avec-ou-sans appeler l'appel interne à flush()
(qui est ce qui force le transfert vers le système d'exploitation). L'activation du vidage (avec la variable debug_mode
) est utile pour les scénarios de débogage où vous souhaitez pouvoir examiner la sortie (pour exemple un fichier disque) lorsque le programme s'est terminé avant de fermer proprement les flux associés (ce qui aurait forcé un vidage final du tampon).
Lors de l'utilisation de std::cout
, les opérandes utilisés après l'opérateur de sortie ( <<
) sont stockés dans un tampon et ne sont pas affichés sur le stdin
(généralement le terminal, ou l'invite de commande) jusqu'à ce qu'ils rencontrent std::endl
ou std::cin
, ce qui provoque le vidage du tampon , en ce sens, afficher/Afficher le contenu du tampon sur le stdin
.
Considérez ce programme:
#include <iostream>
#include <unistd.h>
int main(void)
{
std::cout << "Hello, world";
sleep(2);
std::cout << std::endl;
return 0;
}
La sortie obtenue sera:
après 2 secondes
Bonjour, Monde
Un code simple pour vous montrer les effets des e/s tamponnées en C++
Quelle que soit l'entrée que vous fournissez est mise en mémoire tampon puis transmise aux variables du programme en cas d'entrées.
Regardez le code ci-dessous: // programme pour tester comment les e / s tamponnées peuvent avoir des effets inattendus sur notre programme #comprendre utilisation de l'espace de noms std;
int main()
{
int a;
char c;
cin>>a;
cin>>c;
cout<<"the number is : "<<a;
cout<<"\nthe character is : "<<c;
}
Ici nous avons déclaré deux variables une int et une char si nous entrons le nombre comme " 12d34" cela entraînera l'acceptation de la variable int seulement 12 comme valeur et il va jeter le reste qui sera toujours là dans le tampon. Et dans l'entrée suivante, la variable char acceptera automatiquement la valeur " d" sans même vous demander d'entrée