web-dev-qa-db-ja.com

coutおよびcinにビット単位のシフト(<<および>>)が使用されるのはなぜですか?

タイトルに質問があります。論理的なものがあると確信していますが、今のところ困惑しています!

69
Crowstar

§8.3.1のC++の設計と進化によると:

名前付き出力関数ではなく出力演算子を提供するという考えは、Doug McIlroyによって、UNIXシェルのI/Oリダイレクション演算子(>、>>、|など)と同様に提案されました。

[...]

いくつかの演算子が入力および出力操作で考慮されました: "代入演算子は入力と出力の両方の候補でしたが、間違った方法でバインドされています。つまり、_cout=a=b_はcout=(a=b)として解釈され、ほとんどの人は、入力演算子が出力演算子と異なることを好むようです。演算子_<_および_>_が試されましたが、「より小」および「より大」の意味は、人々の新しいI/Oステートメントはすべての実用的な目的のために判読不能であったことを覚えておいてください(これは<<と>>には当てはまりません)。それとは別に、 '<'はほとんどのキーボードと 'このような表現を書いていた:

_cout < x , y, z;
_

これに対して適切なエラーメッセージを表示することは容易ではありません。

59
Jerry Coffin

おそらく入力/出力ストリームに追加しているので、Unixの追加操作に似ているからでしょうか?

例えば。

出力

echo "foo" >> bar</ code>

入力

sendmail -f [email protected] << myemail.txt

(ザック・ハウランドからの入力例を盗んだ)

17
Abe Voelker

「C++プログラミング言語」より。 Stroustrup(言語の作者)の言葉:

演算子のオーバーロード<<を意味する「プット」は、より良い表記を提供し、プログラマが単一のステートメントでオブジェクトのシーケンスを出力できるようにします。

しかし、なぜ <<?新しい字句トークンを作成することはできません。代入演算子は入力と出力の両方の候補でしたが、ほとんどの人は入力と出力に異なる演算子を使用することを好むようです。さらに、=は間違った方法でバインドします。つまり、cout = a = bは(cout = a)= bではなくcout =(a = b)を意味します。演算子を試してみました<および>、しかし、「以下」と「以上」の平均は人々の心にしっかりと埋め込まれていたため、新しいI/Oステートメントはすべての実用的な目的では判読できませんでした。

11
UmmaGumma

>>および<<は単なる演算子であり、クラスに独自の>>および<<を実装できます。

「誰か」がそれらを選択したと思います:a)それらはシェルファイル操作に似ており、b)新しい演算子を作成する必要がないため、既存の演算子を再利用します。

6
Elalfer

彼らは多かれ少なかれ合理的な優先順位を持っていて、見栄えが良かったからです。 C++では、新しい演算子を作成したり、それらの優先順位やグループ化ルールを変更したりすることはできません。既存の演算子をオーバーロードして、それらが実際に行うことを変更することしかできません。

<<>>を選択すると、出力が順序に従って行われるという考えがどうにか推し進められるため、残念な副作用があります。これは、巧妙な連鎖トリックのおかげで実際の出力には当てはまりますが、関連する計算には当てはまりません。これは、多くの場合驚くべきことです。

より具体的に書くこと

std::cout << foo() << bar() << std::eol;

foobarの前に呼び出されることを意味しません。

編集

C++ 17では、シーケンスの問題が「修正」されました。 <<演算子と>>演算子の評価順序が左から右に指定されています。 C++にはまだ評価の順序が指定されていない場所(または存在しない場合でも評価をインターリーブできること)がありますが、いくつかの一般的なケースが予測可能で移植可能な方法で動作するようになりました this answer を参照してください。

6
6502

ですから、cinをキーボード、coutをモニターと考えると、入力したものが変数に入ることに注意してください。

cin>>var;

または、変数の内容が画面に表示されます

cout<<var;

これらはビット単位の演算子ではなく、このコンテキストでは挿入演算子および抽出演算子と呼ばれます。

http://www.cplusplus.com/doc/tutorial/basic_io/

これらは視覚的な解釈にのみ使用されます。独自のストリームとオペレーターのオーバーロードの開発を検討すると、入力に+を、出力に-を使用することさえできることがわかります:)

3
Sarwar Erfan

この答えは満足のいくものではありませんが、正解です。これらはビット単位の演算子ではありません。

演算子の意味は、左側に表示されるデータ型によって決まります。 cinおよびcout(およびその他のストリームタイプ)の場合、<<および>>演算子は、ストリーム間で値を移動します。左側のオペランドが整数である場合、演算は、Cですでにわかっているビット演算です。

優先順位は固定ですが、演算子の意味は固定されていません。

3
Kevin A. Naudé

主にそれらの関連性のためです。挿入演算子と抽出演算子は左から右に関連付けられるため、

std::cout << "Hello" << ' ' << 4 << 2;

期待どおりに評価します:最初に"Hello"、次に' 'そして最後に4および2。確かに、加算演算子operator+も左から右に関連付けます。しかし、その演算子と左から右への結合性を持つ他の演算子は、すでに別の意味を持っています。

3
wilhelmtell

Bjarneは、実用的な優先順位、結合性、ニーモニック値のためにそれらを選択しました。

優先順位は完全ではありません。ブール演算子とビットレベル演算子は面倒です。

しかし、それはかなり大丈夫です。

入力ストリームはプログラムへのデータの流れを意味し、出力ストリームはプログラムからのデータの流れを意味するため、挿入演算子>><<はそれぞれ入力ストリームと出力ストリームで使用されます。これらの挿入演算子は方向演算子(データの流れの方向を示す)に似ているため、>>が入力ストリームに、<<が出力ストリームに選択されます。

コードの一部を見てください...

int Num1;
cin >> Num1;

ここを注意深く観察すると、>>は変数(プログラムで宣言)へのデータの流れを示しています。これは、入力ストリーム(ここではcin)の仕事であるプログラムへのデータの流れを意味します。

同様にcout

int Num2 = 5;
cout << Num2;

ここで<<は、プログラムからのデータの流れを示しています(Num2はプログラムの一部です)。これは、出力ストリームの仕事です。

このすべてがあなたにとって意味のあるものであることを願っています。

1
Gopal Sharma
cout << "Output sentence"; // prints Output sentence on screen
cout << 120;               // prints number 120 on screen
cout << x;                 // prints the content of x on screen 

<<演算子は、それに続くデータをその前のストリームに挿入します。上記の例では、定数文字列の出力文、数値定数120、変数xを標準出力ストリームcoutに挿入しました。

標準入力デバイスは通常キーボードです。 C++での標準入力の処理は、cinストリームにオーバーロードされた抽出演算子(>>)を適用することによって行われます。演算子の後には、ストリームから抽出されるデータを格納する変数が続く必要があります。例えば:

int age;
cin >> age;
0
ayush

C++では演算子のオーバーロードが可能であることをご存知だと思います。一般に、セマンティクスが完全に転送可能である場合にのみ演算子をオーバーロードします(たとえば、2つのベクトルを一緒に追加するためのベクトルクラスの追加のオーバーロード)。あなたの質問は、なぜビットシフト演算子を使用し、iostreamのためにそれらをオーバーロードし、それらに元の目的とはまったく異なる意味を与えるのかについて言及していると思います。これを実行できる理由は、ビットシフト操作がiostreamの処理から遠く離れているため、<<または>>がiostreamでビットシフトを実行していると誤解することがないためです。また、これらを使用すると便利な理由は、順序付けが最初に左側のオペランドを評価し、次に右側のオペランドを評価して、演算を実行するためです。これは、演算子を使用してiostreamからデータを追加または抽出するときに何をしたいかに当てはまります。

しかし、元の質問に対して、なぜですか?よくわかりませんが、<<と>>は、一方のエンティティから情報を取得し、もう一方のエンティティに情報を入力することで簡単に理解できるように思えます。なぜそれよりも理由を複雑にする必要があるのですか?それらの意味が明白であるため、これらを使用するのが賢明に見えます。

0
Mikael Persson