为什么按位移位(< < 和 > >)用于 cout 和 cin?

问题其实就在标题里,我相信有些东西是合乎逻辑的,但是现在我被难住了!

24598 次浏览

Maybe because it looks similar to the Unix append operation, as you are essentially appending to an input/output stream?

E.g.

Output

echo "foo" >> bar

Input

sendmail -f test@domain.com << myemail.txt

(Stole input example from Zac Howland)

So you remember that if you think cin as a keyboard and cout as a monitor, what you type goes into the variable

cin>>var;

Or the contents of your variable goes towards the screen

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

The << operator inserts the data that follows it into the stream preceding it. In the examples above it inserted the constant string Output sentence, the numerical constant 120 and variable x into the standard output stream cout.

The standard input device is usually the keyboard. Handling the standard input in C++ is done by applying the overloaded operator of extraction (>>) on the cin stream. The operator must be followed by the variable that will store the data that is going to be extracted from the stream. For example:

int age;
cin >> age;

>> and << are just operators and you can implement your own >> and << for your classes.

I suppose "somebody" selected them because: a) they are similar to shell file operations and b) to reuse existing operators because there are no need to create new ones

They are not bitwise operators, They are called insertion and extraction operators in this context.

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

These are used only for visual interpretation. If you study developing own stream and operator overloading, then you can see that you can even use + for input and - for output :)

This answer is unsatisfying but correct: they aren't bitwise operators.

The meaning of the operator is determined by the data-type that appears on its left. In the case of cin and cout (and other stream types) << and >> operators move values to and from streams. In the case that the left operand is an integer, the operation is the bitwise operation that you already know from C.

The meaning of the operator is not fixed, although its precedence is.

According to §8.3.1 of The Design and Evolution of C++:

The idea of providing an output operator rather than a named output function was suggested by Doug McIlroy by analogy with the I/O redirection operators in the UNIX shell (>, >>, |, etc.)

[...]

Several operators were considered for input and output operations: the assignment operator was a candidate for both input and output, but it binds the wrong way. That is cout=a=b would be interpreted as cout=(a=b), and most people seemed to prefer the input operator to be different from the output operator. The operators < and > were tried, but the meanings "less than" and "greater than" were so firmly implanted in people's minds that the new I/O statements were for all practical purposes unreadable (this does not appear to be the case for << and >>). Apart from that, '<' is just above ',' on most keyboards, and people were writing expressions like this:

cout < x , y, z;

It is not easy to give good error messages for this.

I assume that you are aware that C++ allows for operator overloading. In general, you overload operators only if the semantics are completely transferable (e.g. overloading the addition for a vector class to add two vectors together). I think your question refers to why one would use bitshift operators, overload them for the iostream, and give them a completely different meaning than their original purpose. The reason it can be done is because bitshift operations are so far removed from what iostreams do that no one could be confused into thinking that << or >> is doing a bitshift on an iostream. And the reason why they are convenient to use also is that their ordering is to evaluate the operand on the left first, then the one on the right, and do the operation. This fits to what you would want to happen when you are using the operators to append or extract stuff from an iostream.

But, to the original question, why? I don't really know, it just seems to me like the << and >> are pretty easily understood as taking information from one entity and putting it in the other. Why does the reason need to be more complicated than that? It looks sensible to use those because their meaning is obvious.. what better could you ask of an operator?

From "The C++ Programming language". Stroustrup's(language authors) words:

Overloading the operator << to mean ‘‘put to’’ gives a better notation and lets the programmer output a sequence of objects in a single statement.

But why <<? It is not possible to invent a new lexical token . The assignment operator was a candidate for both input and output, but most people seemed to prefer to use different operators for input and output. Furthermore, = binds the wrong way; that is, cout=a=b means cout=(a=b) rather than (cout=a)=b . I tried the operators < and >, but the mean ‘‘less than’’ and ‘‘greater than’’ were so firmly implanted in people’s minds that the new I/O statements were for all practical purposes unreadable.

Mostly because of their associativity. The insertion and extraction operators associate from left to right, so

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

evaluates as you'd expect: first with "Hello", then with ' ' and finally with 4 and 2. Granted, the addition operator, operator+ also associates from left to right. But that operator and others with left-to-right associativity already have a different meaning.

Because they had more or less a reasonable precedence and looked good. In C++ you cannot create new operators or change their precedence or grouping rules, you can only overload existing ones and changing what they actually do.

The choice of << and >> has some unfortunate side effect because it's somehow pushing the idea that the output will be done respecting the order. While this is true for the actual output thanks to a clever chaining trick it's however false for the computations involved and this is very often surprising.

To be more specific writing

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

does NOT imply that foo will be called before bar.

EDIT

With C++17 the sequence problem has been "fixed". Now the order of evaluation is specified to be left-to-right for << and >> operators. There are still places in C++ where the order of evaluation is unspecified (or even non-existing meaning that evaluation can be interleaved) but a few common cases now behave in a predictable and portable way see this answer .

Bjarne chose them for practical precedence, associativity and mnemonic value.

The precedence isn't perfect, e.g. the boolean and bit-level operators are troublesome.

But it's fairly OK.

Insertion operator >> and << are used with Input Stream and Output Stream respectively because Input stream means flow of data into your program and Output stream means flow of data out of your program. As these insertion operators look like Directional operator (Showing direction of flow of data), so >> is chosen for Input stream and << for the Output stream.

Have a look at the part of code...

int Num1;
cin >> Num1;

here if you observe carefully >> is showing flow of data to variable (declared in program) that means the flow of data to the program , which is a job of Input stream (here cin).

similarly goes with cout,

int Num2 = 5;
cout << Num2;

Here << showing the flow of data out of the program (as Num2 is part of the program), which is the job of Output stream.

I hope all this make sense to you.