J'ai utilisé "Accelerated C++" pour apprendre le C++ au cours de l'été, et il y a un concept que je ne semble pas comprendre correctement.
Pourquoi est-ce
int x;
if (cin >> x){}
équivalent à
cin >> x;
if (cin){}
En regardant le code, il me semble que nous utilisons cin comme variable. Mais, je pensais que c'était une fonction. Pourquoi pouvons-nous utiliser cin de cette manière quand c'est x qui a la valeur que nous entrons dans notre clavier?
cin
est un objet de classe istream
qui représente le flux d'entrée standard. Il correspond au cstdio
stream stdin
. L'opérateur >>
overload pour les flux renvoie une référence au même flux. Le flux lui-même peut être évalué dans une condition booléenne à true ou false via un opérateur de conversion.
cin
fournit une extraction de flux formatée. L'opération cin >> x;
où "x" est un int échouera si une valeur non numérique est entrée. Donc:
if(cin>>x)
renverra false
si vous entrez une lettre plutôt qu'un chiffre.
Ce site Web sur trucs et astuces en utilisant les E/S C++ vous aidera également.
Remarque: la réponse a été mise à jour quatre ans après coup pour traiter à la fois C++ 98/03 et C++ 11 (et au-delà).
std::cin
Est une instance d'un std::istream
. Cette classe fournit deux surcharges liées à cette question.
operator >>
Lit les données du flux dans la variable cible si cela est possible. Si le contenu immédiat du flux ne peut pas être traduit dans le type de la variable cible, le flux est plutôt marqué comme non valide et la variable cible reste intacte. Quel que soit le succès/l'échec de l'opération, la valeur de retour est une référence au flux.operator void*()
(pré-C++ 11), qui convertit la référence de flux en un pointeur void*
, Soit explicit operator bool()
(C++ 11), qui convertit le stream référence à un booléen. Le résultat de cette conversion est un pointeur non nul (pré-C++ 11) ou true
(C++ 11) si le flux est valide, mais le pointeur nul (pré-C++ 11) ou false
(C++ 11) si le flux n'est pas valide.Une instruction if
a besoin d'un booléen, d'un entier ou d'un pointeur comme quantité à tester. Le résultat de std::cin >> x
Est une référence à un istream
, qui n'est rien de ce qui précède. Cependant, la classe istream
possède ces opérateurs de conversion qui peuvent être utilisés pour transformer la référence istream
en quelque chose utilisable dans une instruction if
. Il s'agit de l'opérateur de conversion spécifique à la version que la langue utilise pour le test if
. Étant donné que l'échec de la lecture marque le flux comme non valide, le test if
échouera si la lecture n'a pas fonctionné.
La raison du membre de conversion operator void*
Plus compliqué avant C++ 11 est que ce n'est qu'en C++ 11 que le mot clé explicit
déjà existant a été étendu pour s'appliquer aux opérateurs de conversion en tant que ainsi que les constructeurs. Une operator bool()
non explicite aurait présenté beaucoup trop d'occasions aux programmeurs de se tirer une balle dans le pied. Il y a également des problèmes avec operator void*()
. "L'idiome de booléen sûr" aurait été un correctif, mais simplement étendre explicit
a accompli exactement ce que l'idiome de booléen sûr accomplit, et sans avoir à utiliser beaucoup de magie SFINAE.
cin
est une variable (globale) de type istream
, pas une fonction.
La classe istream
remplace la >>
pour effectuer la saisie et renvoyer une référence à l'objet sur lequel vous l'avez appelé (cin
).
cin
est variable dans std
namespace.
operator>>
renvoie la référence à cin
, à cause de cela, vous pouvez écrire: cin >> a >> b
, au lieu de cin >> a; cin >> b;
Les réponses ci-dessus sont informatives. Ici, je donne juste un commentaire supplémentaire.
std::cin
Est un objet de classe istream
et représente le flux d'entrée standard (ie le clavier) qui correspond à stdin
dans le flux C .
cin >> x
Lit d'abord un entier dans le flux d'entrée standard et l'affecte à x
. Après cela, renvoyez une auto référence à cin
. Ainsi, la valeur de retour de l'appel de fonction cin >> x
Est toujours cin
.
Donc, du point de if condition , if(cin)
et if(cin >> x)
se ressemblent. La bibliothèque IO standard définit une fonction pour le flux comme ceci (dépend de l'implémentation):
explicit operator bool() const; // C++11
ou
operator void*() const; //C++98, C++2003
De ces deux déclarations, nous savons qu'ils cast le type de flux directement ou indirectement (via void*
Pointeur vers bool
ce qui est évident) en bool
type.
Dans ces deux fonctions, elles dépendent de certains états de base IO Steam (champs de classe) pour déterminer si retourner faux ou vrai (pour void*
cas, c'est nullptr
ou pas).
cin
est une instance de la classe istream
qui hérite de la fonction casting-to-bool. Alors ça marche!
parce que le résultat de l'expression
cin >> x
évalue à
cin
après la lecture du flux.
Comme je sais, l'opérateur surchargé >> retourne un objet de classe istream. Voilà pourquoi ici n'est pas différent
1) cin
est une instance de istream
, voir http://www.cplusplus.com/reference/iostream/cin/ .
2) l'opérateur >>
De istream
renverra son opérande gauche, dans ce cas c'est cin
, voir http://www.cplusplus.com/ référence/istream/istream/operator% 3E% 3E / . Cet opérateur activera failbit
si aucun caractère n'a été extrait de cin
, au cas où le lecteur a terminé EOF
donc il n'y aura plus de caractère à lire.
3) À partir du 2) ci-dessus, lorsque la condition est évaluée après l'opération de lecture, if (cin >> x)
doit être comme if (cin)
, reportez-vous à ce lien http: // www .cplusplus.com/reference/ios/ios/operator_bool / vous verrez que ce bloc if
renverra:
Un pointeur nul si au moins l'un de failbit
ou badbit
est défini. Sinon, une autre valeur (pour la norme C++ 98).
La fonction renvoie false si au moins un de ces indicateurs d'erreur est défini, et true sinon. (pour la norme C++ 11)
parce que cin est un objet de classe, lisez plus sur http://www.cplusplus.com/reference/iostream/cin/ .