3

An exercise about standard io asks me to:

Read input from the standard input and write it to the standard output.

A possible solution is:

#include<iostream>
#include<string>

using std::cin; using std::cout;
using std::string;

int main()
{
    string word;
    while (cin >> word)
        cout << word;

    return 0;
}

The string acts as a buffer in this example. If one tries to get rid of the buffer by doing something like this:

#include<iostream>
using std::cin; using std::cout;

int main()
{
    while (cout << cin)
        ;
    return 0;
}

the results are very different. When I run this code I get an interminable stream of

0x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d30

on the terminal.

Why this happens? Why do these programs behave differently?

Jose_mr
  • 331
  • 2
  • 10

2 Answers2

6

cout << cin will not work the way you want it to. In C++11 and later, it won't even compile.

You are seeing an unfortunate side-effect of the (now obsolete) "safe bool" idiom.

Before C++11, a std::istream could be implicitly converted to a void* to emulate bool semantics. (Since C++11, explicit operator bool() const fills that role)

Therefore, the code:

while (cout << cin)

compiles in C++98 or C++03, because it can be implicitly converted to:

while (cout << static_cast<void*>(cin) )

This cast is allowed to produce any non-NULL void* when cin is not in an error state. In your case, it is producing the pointer 0x600d30.

Community
  • 1
  • 1
Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • +1, but telling how one can accomplish the OP's desired behavior would grant you a +2 (if I could vote twice). – Enlico Feb 17 '20 at 17:25
  • 1
    @EnricoMariaDeAngelis I'm inclined to agree, but in this case the OP has already shown desired behavior in the question, and is only asking why `cout< – Drew Dormann Feb 17 '20 at 21:22
1

In first solution, you extract a string from cin and reinject it in cout. But in the second way, compiler tries to convert cin into a value suitable for injection in cout.

Your implementation converted cin to a pointer and repeatedly printed it. Mine simply converted cin to a bool and repeadedly prints 1.

But beware, even your first version is not transparent to multiple spaces or tabs, and would probably not respect lines either. I would prefer:

#include<iostream>
#include <string>


int main()
{
    std::string line;

    while (std::getline(std::cin, line)) {
        std::cout << line << std::endl;
    }
    return 0;
}
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252