if (cin >> x) – ¿Por qué puedes usar esa condición?

He estado usando “C ++ acelerado” para aprender C ++ durante el verano, y hay un concepto que no parezco entender correctamente.

Por que es

int x; if (cin >> x){} 

equivalente a

 cin >> x; if (cin){} 

Al mirar el código, me parece que estamos usando cin como una variable. Pero, pensé que era una función. ¿Por qué podemos usar cin de esta manera cuando x tiene el valor que ingresamos en nuestro teclado?

cin es un objeto de clase istream que representa el flujo de entrada estándar. Corresponde a la stream de cstdio stdin . La sobrecarga del operador >> para las transmisiones devuelve una referencia a la misma secuencia. La secuencia en sí se puede evaluar en una condición booleana en verdadero o falso a través de un operador de conversión.

cin proporciona una extracción de flujo formateada. La operación cin >> x;

donde “x” es un int fallará si se ingresa un valor no numérico. Asi que:

 if(cin>>x) 

devolverá false si ingresa una letra en lugar de un dígito.

Este sitio web sobre consejos y trucos con C ++ I / O también te ayudará.

Nota: Respuesta actualizada cuatro años después del hecho para abordar C ++ 98/03 y C ++ 11 (y más allá).

std::cin es una instancia de std::istream . Esa clase proporciona dos sobrecargas relacionadas con esta pregunta.

  • operator >> lee los datos del flujo en la variable objective si eso es posible. Si el contenido inmediato de la transmisión no se puede traducir al tipo de la variable de destino, la transmisión se marca como no válida y la variable de destino no se modifica. Independientemente del éxito / fracaso de la operación, el valor de retorno es una referencia a la transmisión.
  • O el operator void*() (pre-C ++ 11), que convierte la referencia de la secuencia en un puntero void* , o explicit operator bool() (C ++ 11), que convierte la referencia de la secuencia en booleana. El resultado de esta conversión es un puntero no nulo (anterior a C ++ 11) o true (C ++ 11) si la secuencia es válida, pero el puntero nulo (anterior a C ++ 11) o false (C + +11) si la transmisión no es válida.

Una instrucción if necesita un booleano, un entero o un puntero como la cantidad que se probará. El resultado de std::cin >> x es una referencia a istream , que no es ninguna de las anteriores. Sin embargo, la clase istream tiene esos operadores de conversión que se pueden usar para transformar la referencia istream en algo utilizable en una sentencia if . Es el operador de conversión específico de la versión que usa el lenguaje para la prueba if . Como la falla en la lectura marca la transmisión como inválida, la prueba if fallará si la lectura no funcionó.

La razón para el miembro de conversión de operator void* más complejo antes de C ++ 11 es que no fue hasta C ++ 11 que la palabra clave explicit ya existente se extendió para aplicarse tanto a operadores de conversión como a constructores. Un operator bool() no explícito operator bool() habría presentado demasiadas oportunidades para que los progtwigdores se peguen un tiro en el pie. También hay problemas con el operator void*() . El “lenguaje bool seguro” habría sido una solución, pero simplemente extender explicit logró exactamente lo que la fraseología bool segura logra, y sin tener que usar mucha magia SFINAE.

cin es una variable (global) de tipo istream , no una función.

La clase istream anula el operador >> para realizar una entrada y devolver una referencia al objeto que lo cin ( cin ).

cin es variable en el std nombres std .

operator>> devuelve referencia a cin , por eso puedes escribir: cin >> a >> b , en lugar de cin >> a; cin >> b; cin >> a; cin >> b;

porque el resultado de la expresión

 cin >> x 

evalúa a

 cin 

después de leer la secuencia

Las respuestas anteriores son informativas. Aquí solo hago un comentario extra.

std::cin es un objeto de clase istream y representa la stream de entrada estándar (es decir, el teclado) que corresponde a stdin en la secuencia C.

cin >> x leería primero un int del flujo de entrada estándar y lo asignaría a x . Después de eso, devuelve una auto referencia a cin . Entonces, el valor de retorno de la función llamada cin >> x sigue siendo cin .

Entonces, desde el punto de si condición , if(cin) y if(cin >> x) parecen entre sí. La biblioteca IO estándar define una función para la transmisión de esta manera (depende de la implementación):

 explicit operator bool() const; // C++11 

o

 operator void*() const; //C++98, C++2003 

A partir de estas dos declaraciones, sabemos que emiten el tipo de flujo directa o indirectamente (a través de void* pinter a bool que es obvio) al tipo bool .

Dentro de estas dos funciones, dependen de algunos estados de vapor IO básicos (campos de clase) para determinar si el resultado es falso o verdadero (para el caso void* , es nullptr o no).

cin es una instancia de la clase istream que hereda la función de conversión a bool . ¡Así que funciona!

porque cin es un objeto de clase, lee más en http://www.cplusplus.com/reference/iostream/cin/ .

Como sé, el operador sobrecargado >> devuelve un objeto de clase istream. Por eso aquí no hay diferentes

1) cin es una instancia de istream , ver http://www.cplusplus.com/reference/iostream/cin/ .

2) el operador >> de istream devolverá su operando izquierdo, en este caso es cin , ver http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ . Este operador configurará failbit si no se extrajeron los caracteres del cin , en caso de que el lector haya finalizado EOF por lo que no habrá más caracteres para leer.

3) A partir del 2) anterior, cuando la condición se evalúa después de la operación de lectura, if (cin >> x) debe ser como if (cin) , consulte este enlace http://www.cplusplus.com/reference/ ios / ios / operator_bool / verá que, este if bloque volverá:

  • Un puntero nulo si se establece al menos uno de failbit o badbit . Algunos otros valores de lo contrario (para el estándar C ++ 98).

  • La función devuelve falso si al menos uno de estos indicadores de error está configurado, y verdadero de lo contrario. (para el estándar C ++ 11)