夏の間、「Accelerated C++」を使用して C++ を学習してきましたが、正しく理解していないように見える概念があります。
なぜですか
int x;
if (cin >> x){}
に相当
cin >> x;
if (cin){}
コードを見ると、cin を変数として使用しているように思えます。しかし、私はそれが機能だと思いました。キーボードに入力した値が x であるのに、なぜ cin をこのように使用できるのでしょうか?
夏の間、「Accelerated C++」を使用して C++ を学習してきましたが、正しく理解していないように見える概念があります。
なぜですか
int x;
if (cin >> x){}
に相当
cin >> x;
if (cin){}
コードを見ると、cin を変数として使用しているように思えます。しかし、私はそれが機能だと思いました。キーボードに入力した値が x であるのに、なぜ cin をこのように使用できるのでしょうか?
cin
istream
標準入力ストリームを表すクラスのオブジェクトです。cstdio
ストリームに対応していますstdin
。ストリームの演算子の>>
オーバーロードは、同じストリームへの参照を返します。ストリーム自体は、ブール条件で true または false に変換演算子を介して評価できます。
cin
フォーマットされたストリーム抽出を提供します。操作
cin >> x;
ここで、「x」は int であり、数値以外の値を入力すると失敗します。そう:
if(cin>>x)
false
数字ではなく文字を入力すると返されます。
C++ I/O を使用したヒントとコツに関するこの Web サイトも役立ちます。
注: C++98/03 と C++11 (およびそれ以降) の両方に対処するために、事実から 4 年後に回答が更新されました。
std::cin
のインスタンスですstd::istream
。そのクラスは、この質問に関連する 2 つのオーバーロードを提供します。
operator >>
可能であれば、ストリームからターゲット変数にデータを読み取ります。ストリームの直接の内容をターゲット変数の型に変換できない場合、ストリームは代わりに無効としてマークされ、ターゲット変数はそのまま残ります。操作の成功/失敗に関係なく、戻り値はストリームへの参照です。operator void*()
変換する (pre-C++11)、またはストリーム参照をブール値に変換する (C++11) のいずれかです。この変換の結果は、ストリームが有効な場合は非 null ポインター (C++11 より前) または (C++11) になりますが、null ポインター (C++11 より前) または(C++11 ) ) ストリームが有効でない場合。void*
explicit operator bool()
true
false
ステートメントには、テストするif
量としてブール値、整数、またはポインターが必要です。の結果は、上記のいずれでもないstd::cin >> x
への参照です。istream
ただし、クラスには、参照をステートメントで使用可能なものistream
に変換するために使用できる変換演算子があります。これは、言語がテストに使用するバージョン固有の変換演算子です。読み取りに失敗するとストリームが無効とマークされるため、読み取りが機能しない場合、テストは失敗します。istream
if
if
if
C++11 より前のより複雑な変換メンバーの理由は、operator void*
C++11 まで既存のexplicit
キーワードが変換演算子とコンストラクターに適用されるように拡張されていなかったためです。明示的operator bool()
でない場合、プログラマーが自分自身を撃つ機会が多すぎます。などの問題もありoperator void*()
ます。「安全な bool イディオム」で修正できたはずですが、単純に拡張するだけexplicit
で、多くの SFINAE マジックを使用することなく、安全な bool イディオムが達成することを正確に達成できました。
cin
istream
関数ではなく、型の (グローバル) 変数です。
このistream
クラスは、>>
演算子をオーバーライドして入力を実行し、呼び出したオブジェクトへの参照を返します ( cin
)。
cin
std
名前空間の変数です。
operator>>
への参照を返しますcin
。そのため、次のように書くことができます:cin >> a >> b
の代わりにcin >> a; cin >> b;
上記の回答は有益です。ここで、追加のコメントをします。
std::cin
クラスのオブジェクトであり、Cの streamに対応する標準入力ストリーム(つまり、キーボード) をistream
表します。 stdin
cin >> x
は、最初に標準入力ストリームから int を読み取り、それを に割り当てますx
。その後、 への自己参照を返しcin
ます。したがって、関数呼び出しの戻り値cin >> x
はまだcin
です。
if 条件の点から、if(cin)
とif(cin >> x)
は似ています。標準IO ライブラリは、次のようなストリームの関数を定義します (実装によって異なります)。
explicit operator bool() const; // C++11
また
operator void*() const; //C++98, C++2003
この 2 つの宣言から、ストリーム型を直接または間接的に (明らかなピンターを介して) 型にキャストすることがわかります。void*
bool
bool
この 2 つの関数内では、いくつかの基本的なIO ストリームステータス (クラス フィールド) に依存して、false を返すか true を返すかを決定します (void*
場合によっては、そうであるかどうかnullptr
)。
cin
は、 casting-to-bool関数istream
を継承するクラスのインスタンスです。だからうまくいく!
1)cin
のインスタンスです。 http://www.cplusplus.com/reference/iostream/cin/istream
を参照してください。
2) の>>
演算子はistream
左オペランドを返します。この場合は です。 http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/cin
を参照してください。この演算子は、 から文字が抽出されなかった場合にオンに設定されます。これは、リーダーが終了したため、読み取る文字がもうない場合です。failbit
cin
EOF
3) 上記 2) の時点で、読み取り操作の後に条件が評価さif (cin >> x)
れるとif (cin)
、このリンクhttp://www.cplusplus.com/reference/ios/ios/operator_bool/を参照すると、このif
ブロックは以下を返します:
failbit
またはの少なくとも 1 つbadbit
が設定されている場合は、null ポインター。それ以外の場合のその他の値 (C++98 標準の場合)。
これらのエラー フラグの少なくとも 1 つが設定されている場合、関数は false を返し、それ以外の場合は true を返します。(C++11 標準用)
std::cin
std::istream
クラスのインスタンスです。
cin >> x
cin
オブジェクトの関数を呼び出すだけです。関数を直接呼び出すことができます:
cin.operator >>(x);
一度に複数の変数を読み取れるようにするために、operator >>
関数は呼び出されたストリームへの参照を返します。あなたは呼び出すことができます:
cin >> x >> y;
または同等:
cin.operator >>(x).operator >>(y);
また:
std::istream& stream = cin.operator >>(x);
stream.operator >>(y);
パズルの最後の部分は、 にstd::istream
変換できることbool
です。bool は を呼び出すことと同じ!fail()
です。
したがって、次のコードでは:
int x;
std::istream& stream = std::cin.operator >>(x);
bool readOK = !stream.fail();
if (readOK)
{
std::cout << x << "\n";
}
bool readOK = !stream.fail();
だけに減らすことができますbool readOK = stream;
。
bool
ストリームの状態を保存するために別の を必要としないので、if (stream)
.
一時stream
変数を削除すると、 が得られif (std::cin.operator >>(x))
ます。
演算子を直接使用すると、元のコードに戻ります。
int x;
if (std::cin >> x)
{
std::cout << x << "\n";
}
cin はクラスのオブジェクトであるため、詳細についてはhttp://www.cplusplus.com/reference/iostream/cin/を参照してください。