Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how does cout << actually work?

Tags:

c++

cout

I was wondering how std::cout is able to use << as it does.

My main puzzlement is with whether std::cout as an instance of something. Basically, how is << defined? If I do this for a custom class, I need an instance of some sort...

I could see implementing it as kind of a hack with void pointers or something, but I'd like to see the actual way it's done.

Does anyone here know? Thanks

like image 590
Ori Avatar asked Apr 01 '11 03:04

Ori


People also ask

What does the cout << statement do?

The cout object is used to display the output to the standard output device. It is defined in the iostream header file.

How does the cout function work in C++?

The cout object in C++ is an object of class ostream. It is defined in iostream header file. It is used to display the output to the standard output device i.e. monitor. It is associated with the standard C output stream stdout.

Why is << used in C++?

In case of std::cout , << is used to write to standard output. >> is not overloaded for std::cout . So std::cout >> x would give compilation error. In case of std::cin , >> is used to read from standard input. << is not overloaded for std::cin .

What exactly is cout?

so cout << "hello" means output to screen when cin >> a means asks from a user input for variable a. cout can also use "+" like for example you can add more strings to one stream like this.


1 Answers

std::cout is an instance of std::ostream. std::cout << "something" calls one of the operator<< overloads as would be done for any instance of std::ostream.

It's "special" in that it references the console, but otherwise it behaves exactly as an ofstream or an ostringstream would.

EDIT: Chaining works just like it works for any other operators. Consider:

class MyType {     friend std::ostream& operator<<(std::ostream& target, const MyType& source);     int val; public:     MyType()         : val(0)     { }     MyType& Add(int toAdd)     {         val += toAdd;         return *this;     } };  MyType& operator+(MyType& target, int toAdd) {     return target.Add(toAdd); }  std::ostream& operator<<(std::ostream& target, const MyType& source) {     target << source.val;     return target; //Make chaining work }  int main() {     MyType value1;     value1 + 2 + 3 + 4;     std::cout << value1 << " and done!" << std::endl; } 

In this case, the chaining for +s on MyType work for the same reason the <<s work on top of std::ostream. Both + and << are left-associative, which means they're evaluated from left to right. In the case of overloaded operators, the operator is replaced with the equivalent function call.

EDIT2: In a bit more detail:

Let's say you're the compiler and you're parsing

std::cout << value1 << " and done!" << std::endl; 

First, << is left associative, so you start on the left. You evaluate the first << and turn it into the function call:

operator<<(std::cout, value1) << " and done!" << std::endl; 

You then see that you once again have a std::ostream (the result of the call to operator<<), and a char *, which you once again turn into the function call:

operator<<(operator<<(std::cout, value1)," and done!") << std::endl; 

and so on until you've processed the entire statement.

like image 148
Billy ONeal Avatar answered Sep 25 '22 21:09

Billy ONeal