Question

Je sais que Cout ont tamponner il y a plusieurs jours, et quand je google, il est dit que le tampon est un peu comme une pile et obtenir la sortie Cout et printf de droite à gauche, puis les mettre hors (au console ou d'un fichier) de haut en bottem. Comme cela,

a = 1; b = 2; c = 3;
cout<<a<<b<<c<<endl;
buffer:|3|2|1|<-   (take “<-” as a poniter)

output:|3|2|<-     (output 1)
        |3|<-       (output 2)
        |<-         (output 3)

Alors j'écris un code ci-dessous,

#include <iostream> 
using namespace std; 
int c = 6;
int f() 
{   
    c+=1; 
    return c; 
} 

int main() 
{ 
     int i = 0; 
     cout <<"i="<<i<<" i++="<<i++<<" i--="<<i--<<endl; 
     i = 0;
     printf("i=%d i++=%d i--=%d\n" , i , i++ ,i-- );

     cout<<f()<<" "<<f()<<" "<<f()<<endl; 
     c = 6;
     printf("%d %d %d\n" , f() , f() ,f() );
     system("pause");
     return 0; 
}

Sous VS2005, la sortie est

i=0 i++=-1 i--=0
i=0 i++=-1 i--=0
9 8 7
9 8 7

Il semble que le chemin de la pile est bonne ~ Cependant, je l'ai lu Primer C ++ De plus hier, et il est dit que le travail de Cout de gauche à droite, à chaque fois que le retour d'un objet (Cout), donc «C'est la fonctionnalité qui vous permet de concaténer sortie en utilisant l'insertion ». Mais de gauche à droit chemin ne peut pas expliquer Cout <

Alors Alnitak me dire que, « L'opérateur << est vraiment ostream & operator << (ostream & os, int), donc une autre façon d'écrire c'est: opérateur << (opérateur << (opérateur << (Cout, a), b), c) »,

Si l'argument est d'abord évaluée plus juste, il peut être un peu expliqué.

Maintenant, je suis confus sur la façon dont le travail de la mémoire tampon de Cout, quelqu'un peut me aider?

Était-ce utile?

La solution

Vous mélangez beaucoup de choses. À ce jour:

  • Détails d'implémentation de cout
  • appels Chained
  • conventions d'appel

Essayez de lire sur eux séparément. Et ne pas penser à tous en une seule fois.

  

printf ( "% i = d i ++ =% d i - =% d \ n", i, i ++, I--);

La ligne ci-dessus invoque un comportement non défini. Lire la FAQ 3.2 . Notez ce que vous observez est un effet secondaire de la convention d'appel de la fonction et les paramètres de manière sont passés dans la pile par une mise en oeuvre particulière (à savoir le vôtre). Ce n'est pas garanti même si vous travaillez sur d'autres machines.

Je pense que vous confondez l'ordre de la fonction des appels avec mise en mémoire tampon. Lorsque vous avez une déclaration suivie par plusieurs << insertions vous invoquez <=> fait des appels de fonctions multiples, l'un après l'autre. Donc, si vous deviez écrire:

cout << 42 << 0;

Cela signifie vraiment: Vous appelez,

cout = operator<<(cout, 42)

puis utilisez le retour dans un autre appel au même opérateur:

cout = operator<<(cout, 0)

Qu'est-ce que vous avez testé par ce qui précède ne vous dirai pas quoi que ce soit de représentation interne de <=>. Je vous suggère de jeter un regard sur les fichiers d'en-tête pour en savoir plus.

Autres conseils

Tout comme une pointe générale, jamais utiliser i ++ dans la même ligne qu'une autre utilisation de i ou i -.

Le problème est que les arguments de fonction peuvent être évalués dans un ordre quelconque, donc si vos arguments de la fonction ont des effets secondaires (tels que les opérations d'augmentation et de diminution) vous ne pouvez pas garantir qu'ils fonctionneront dans l'ordre que vous attendez. Ceci est quelque chose à éviter.

La même chose vaut pour ce cas, qui est similaire à l'expansion réelle de votre utilisation de Cout:

function1 (function2 (foo), bar);

Le compilateur est libre de evaulate bar avant d'appeler fonction2, ou vice versa. Vous pouvez garantir que fonction2 sera de retour avant function1 est appelé, par exemple, mais pas que leurs arguments sont évalués dans un ordre spécifique.

Cela devient un problème quand vous faites quelque chose comme:

function1 (function2 (i ++), i);

Vous avez aucun moyen de spécifier si le « i » est évaluée avant ou après le « i ++ », donc vous êtes susceptible d'obtenir des résultats qui sont différents que vous attendez, ou des résultats différents avec des compilateurs différents ou même des versions différentes de le même compilateur.

En bout de ligne, éviter les déclarations avec des effets secondaires. Ne les utilisez que si elles sont la seule déclaration sur la ligne ou si vous savez que vous ne modifier une fois la même variable. (Une "ligne" désigne une instruction unique, plus virgule.)

Ce que vous voyez est un comportement non défini.

Local i et mondial sont c ajoutées / soustraites plusieurs fois sans point de séquence. Cela signifie que les valeurs que vous obtenez peut être à rien. Cela dépend de compilateur, peut-être également l'architecture de processeur et le nombre de noyaux.

Le tampon cout peut être considéré comme la file d'attente, de sorte que Alnitak est droite.

En plus des autres réponses qui soulignent à juste titre que vous voyez un comportement non défini, je pensais que je vous signale que utilise un objet std::cout de type à faire sa std::streambuf mise en mémoire tampon interne. Fondamentalement, il est une classe abstraite qui représente de tampon (la taille est propre à la mise en œuvre et peut même être 0 pour les tampons de flux unbufferd). Celui est écrit pour <=> de telle sorte que quand il « déborde », il est vidé dans stdout.

En fait, vous pouvez modifier associé à la <=> <=> (ou tout autre flux pour cette matière). Cela a souvent utile si vous voulez faire quelque chose d'intelligent faire comme tous les appels <=> extrémité dans un fichier journal ou quelque chose.

Et comme dirkgently dit vous confondez convention d'appel avec d'autres détails, ils sont tout à fait sans rapport avec la mise en mémoire tampon std :: de cout.

En outre, le mélange des paradigmes de sortie (Cout) printf et sont spécifiques de mise en œuvre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top