简体   繁体   English

为什么我们需要绑定std :: cin和std :: cout?

[英]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); 默认情况下,标准输入设备与标准输出设备绑定在一起: 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. 所以我尝试使用std::cin.tie(0)解开它们,但似乎结果与绑定的没有区别。

#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? 他们共享相同的缓冲区吗?

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. 您的示例中没有任何错误(除了您应该在cin.tie(0)行之后添加分号),以及iostream对象的工作方式。

tie() simply guarantees the flushing of cout before cin executes an input. tie()只是保证在cin执行输入之前刷新cout 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. 但是,如果非tie()cincout ,也不能保证的缓冲cout被刷新。 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. 实际上,如果计算机有足够的资源,它会立即刷新cout缓冲区,因此这会在cin请求输入之前发生。 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. 除了在cin.tie(0) ,不能保证将发生冲洗。 However, in 99% of the cases, that flush-ing will still occur (but it is no longer guaranteed). 但是,在99%的情况下,仍然会发生冲洗(但不再保证)。

In theory, if tied, cin and cout could share the same buffer. 从理论上讲,如果绑定, cincout可以共享相同的缓冲区。 But, I think no implementation does that. 但是,我认为没有实现这样做。 One reason is that the two may be un-tie()d. 一个原因是两者可能是un-tie()d。

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. 要打破发生 - 之前的关系,你应该(仅在标准io的情况下)(1)删除与stdio同步 (2)解开流。

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. 与stdio同步是一种特殊的能力,以便在C-style和C ++风格的输入和输出之后进行适当的发生 - 我强烈反对你在没有真正必要的情况下删除它。

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. 在C中,提示用户输入遵循您发出命令以打印提示消息的模式,然后是输入值的命令。

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. 在DOS(或Windows命令行)环境中, STDOUT是无缓冲的,因此print命令会立即显示该消息。
  • In a *NIX environment, STDOUT is line buffered. 在* NIX环境中, STDOUT是行缓冲的。 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. 因此,如果您在提示消息中遵循* NIX样式包含换行符,以便用户在下一行输入输入,则在输入之前会自动显示提示。

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. tie功能使这种自动刷新行为成为iostream库工作方式的一部分,而不是常规产品。 (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) (虽然请注意,自动刷新仅在程序要求系统获取更多输入时发生,因此存在cin >> c实际上不会刷新的边缘情况)


However! 然而! By default the iostream library is synchronized with the stdio library. 默认情况下,iostream库与stdio库同步 In practice, this means the iostream doesn't do any buffering at all; 在实践中,这意味着iostream根本不做任何缓冲; it simply forward the data over to the underlying C library. 它只是将数据转发到底层C库。

So, this means you're seeing what you what you would normally see if you wrote a similar C program. 所以,这意味着如果您编写了类似的C程序,那么您将看到通常会看到的内容。 If you are in a windows command line environment, output wouldn't be buffered, and so you see the prompt before entering input. 如果您在Windows命令行环境中,则不会缓冲输出,因此您在输入输入之前会看到提示。

To see the native C++ behavior, you need to turn off synchronization by running std::cout.sync_with_stdio(false); 要查看本机C ++行为,您需要通过运行std::cout.sync_with_stdio(false);来关闭同步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). 如果你这样做,那么cout语句将不会刷新输出缓冲区(除非缓冲区非​​常小)。 And since you've removed the tie, the cin statement won't flush it either. 因为你已经删除了领带,所以cin语句也不会刷新它。 So, you'll get the result where you have to enter user input before you see the prompt. 因此,在看到提示之前,您将获得必须输入用户输入的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM