Pregunta

Sé que cout han amortiguar hace varios días, y cuando Google él, se dice que el tampón es un poco como una pila y obtener la salida de cout y printf de derecha a izquierda, a continuación, ponerlos fuera (a la consola o archivo) de arriba hacia bottem. De esta manera,

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)

A continuación escribo un código de abajo,

#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; 
}

En VS2005, la salida es

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

Parece que la forma de pila es correcta ~ Sin embargo, leí C ++ Primer Plus ayer, y se dice que el trabajo cout de izquierda a derecha, cada vez que devuelve un objeto (cout), por lo que "Esa es la función que le permite concatenar la salida mediante el uso de inserción". Pero el de la izquierda a manera correcta no puede explicar cout <

A continuación, Alnitak dime que "el operador << es realmente ostream operador & << (ostream y OS, int), por lo que otra manera de escribir esto es: operador << (operador << (operador << (cout, a), b), c)",

Si se evalúa primero el argumento más acertada, puede ser alguna explicó.

Ahora estoy confundido acerca de cómo el trabajo de búfer cout, puede alguien ayudarme?

¿Fue útil?

Solución

Se está mezclando muchas cosas. Hasta la fecha:

  • detalles de implementación de cout
  • llamadas encadenadas
  • convenciones de llamada

Trate de leer sobre ellos por separado. Y no pensar en todos ellos de una sola vez.

  

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

La línea anterior invoca un comportamiento indefinido. Lea las preguntas frecuentes 3.2 . Tenga en cuenta, lo que se observa es un efecto secundario de la convención de llamada de la función y los parámetros manera se pasan en la pila por una implementación particular (es decir, la suya). Esto no se garantiza que sea el mismo si estuviera trabajando en otras máquinas.

Creo que está confundiendo el orden de las llamadas a funciones con búfer. Cuando usted tiene un << declaración seguida de múltiples inserciones <=> está invocar realmente varias llamadas de función, una tras otra. Así que, si tuviera que escribir:

cout << 42 << 0;

En realidad significa: Usted llama,

cout = operator<<(cout, 42)

y luego usar el regreso en otra llamada al mismo operador que:

cout = operator<<(cout, 0)

Lo que han probado por lo anterior no le dirá nada <=> 's representación interna. Le sugiero que eche un vistazo a los archivos de cabecera para saber más.

Otros consejos

Al igual que un consejo general, no utilice nunca jamás i ++ en la misma línea que otro uso de i o i -.

El problema es que los argumentos de la función se pueden evaluar en cualquier orden, así que si los argumentos de la función tienen efectos secundarios (tales como las operaciones de incremento y decremento) no se puede garantizar que van a operar en el orden que usted espera. Esto es algo a evitar.

Lo mismo vale para este caso, que es similar a la expansión real de su uso cout:

function1 (function2 (foo), bar);

El compilador es libre de evaulate bar antes de llamar function2, o viceversa. Usted puede garantizar que function2 volverá antes function1 se llama, por ejemplo, pero no de que sus argumentos se evalúan en un orden específico.

Esto se convierte en un problema cuando se hace algo como:

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

Usted no tiene ninguna manera de especificar si la "i" se evalúa antes o después de la "i ++", por lo que es probable que obtener resultados que son diferentes de lo esperado, o diferentes resultados con diferentes compiladores o incluso diferentes versiones de el mismo compilador.

En pocas palabras, evitar declaraciones con efectos secundarios. Sólo los usan si son la única declaración en la línea o si sabe que sólo está modificando la misma variable vez. (A "línea" significa una única instrucción plus punto y coma.)

Lo que se ve es un comportamiento indefinido.

se añaden i

locales y globales c / restan varias veces sin punto de secuencia. Esto significa que los valores que recibe pueden ser sobre cualquier cosa. Depende de compilador, posiblemente también la arquitectura del procesador y el número de núcleos.

El cout tampón puede ser pensado como la cola, por lo que Alnitak es correcta.

Además de las otras respuestas que señalan correctamente que usted está viendo un comportamiento indefinido, pensé que había que mencionar que std::cout utiliza un objeto de tipo std::streambuf para hacer su búfer interno. Básicamente se trata de una clase abstracta que representa de tampón (el tamaño es particular de aplicación e incluso puede ser 0 para los búferes de transmisión en unbufferd). El uno para <=> está escrita de tal manera que cuando se "desborda" que se vacía en stdout.

De hecho, se puede cambiar el <=> asociado con <=> (o cualquier corriente para el caso). Esto a menudo útil si desea hacer algo inteligente como hacer toda <=> terminar llamadas en un archivo de registro o algo así.

Y como dicho dirkgently le están confundiendo el convenio de llamada con otros detalles, que son totalmente ajenos a std :: cout de búfer.

Además, la mezcla de paradigmas de salida (printf y cout) son específicos de aplicación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top