std
std

Reputation: 963

Why do we need to tie std::cin and std::cout?

By default, the standard input device is tied together with the standard output device in the form: std::cin.tie (&std::cout); which guarantees that the output buffer has been flushed before input is invoked. So I try to untie them by using std::cin.tie(0), but it seems that the result, has no difference with the tied one.

#include<iostream>
using namespace std;

int main(int argc, char *argv[])
{
    char c;

    cin.tie(0)

    cout << "Please enter c:";
    cin >> c;
    cout << c ;

    return 0;
}

Am I testing wrong? Why do we need to tie them together? Do they share the same buffer?

Upvotes: 28

Views: 15574

Answers (3)

user1084944
user1084944

Reputation:

In C, prompting the user for input followed the pattern where you issued a command to print a prompt message, and then a command to input a value.

In order for this process to work properly, you need to ensure the prompt message is actually displayed. Environments were configured so that this was automatic:

  • In a DOS (or windows command line) environment, STDOUT is unbuffered, so the print command displays the message immediately.
  • In a *NIX environment, STDOUT is line buffered. So, if you followed the *NIX style of including a newline in your prompt message so that the user enters input on the next line, your prompt would display automatically before input.

The tie feature makes this behavior of automatic flushing part of the way in which the iostream library works, rather than a product of convention. (although be aware that the automatic flushing only happens when the program asks the system to obtain more input, so there are edge cases where cin >> c won't actually flush)


However! By default the iostream library is synchronized with the stdio library. In practice, this means the iostream doesn't do any buffering at all; it simply forward the data over to the underlying C library.

So, this means you're seeing what you what you would normally see if you wrote a similar C program. If you are in a windows command line environment, output wouldn't be buffered, and so you see the prompt before entering input.

To see the native C++ behavior, you need to turn off synchronization by running std::cout.sync_with_stdio(false); at the start of your program, as indicated in the other answer.

If you do that, then the cout statement won't flush the output buffer (unless the buffer is very tiny). And since you've removed the tie, the cin statement won't flush it either. So, you'll get the result where you have to enter user input before you see the prompt.

Upvotes: 2

user1284631
user1284631

Reputation: 4606

There is nothing wrong in your example (except that you should add a semi-colon after the cin.tie(0) line), nor with the way iostream objects work.

tie() simply guarantees the flushing of cout before cin executes an input. This is useful for the user to see the question before being asked for the answer.

However, if you un-tie() the cin from cout, there is no guarantee that the buffer of the cout is flushed. But there is no guarantee that the buffer is un-flushed neither. In fact, if the computer has enough resources, it will flush the cout buffer immediately, so this occurs before cin asking for the input. This is the case in your example.

So, everything works well. Except that after cin.tie(0), there is no guarantee that the flush-ing will occur. However, in 99% of the cases, that flush-ing will still occur (but it is no longer guaranteed).

In theory, if tied, cin and cout could share the same buffer. But, I think no implementation does that. One reason is that the two may be un-tie()d.

Upvotes: 30

Konstantin Vladimirov
Konstantin Vladimirov

Reputation: 6999

I think, previous answer is wrong (and I wonder why is it so upvoted and marked as true, being obviously not).

To break happens-before tie, you shall (in the case of standard io only) (1) remove sync with stdio and (2) untie streams.

Like this:

std::cin.tie (nullptr);
std::cout.sync_with_stdio(false);
std::cout << "Please enter c: ";
std::cin >> c;

Then you are guaranteed to have untied streams. Syncing with stdio is special ability in order to have proper happens-after ordering for C-style and C++-style input and output and I strongly discourage you from removing it without real necessity.

Upvotes: 11

Related Questions