我如何解释ios_base :: sync_with_stdio(false)的这种行为; cin.tie(NULL);?

时间:2016-06-28 11:59:16

标签: c++ performance

实际上,通过以下回答 https://stackoverflow.com/a/31165481/6108030 ,我开始了解快速输入/输出。

问题1:

它说如果我使用ios_base::sync_with_stdio(false);,它将禁用C和C ++样式输入/输出之间的同步。 所以根据我的解释,这意味着通过使用这个语句,我将无法在我的C ++代码中使用scanf()(即C风格的I / O)(如果我弄错了,请纠正我)。

但即使使用ios_base::sync_with_stdio(false);后我的代码仍然有效。

这是代码。

int main()
{
  ios_base::sync_with_stdio(false);

  long test; cin>>test;
  while(test--)
  {
       ull f=0,t=0,a,b,c,d,k;
       scanf("%llu %llu %llu %llu %llu",&a,&b,&c,&d,&k); //scanf() used
       while(f<k){                  //
         t++;                       //Irrelevant from a question perspective
         f=a*(t*t*t)+b*(t*t)+c*t+d; //
       }                            //
       if(f==k)
        cout<<(t)<<"\n";
       else
        cout<<(t-1)<<"\n";
}}

/* Expected behaviour

  2             input(no of test)
  2 2 2 2 10    input(a b c d k)
  1             output
  2 3 5 7 1000  input
  7             output

Behavior of this code
  2
  2 2 2 2 10    input
  2 3 5 7 1000  input(prompted)
  1             output
  7             output
*/

这背后的正确理由是什么?

问题2:

答案还指出,cin.tie(NULL)使用来自cin的{​​{1}} cout。 但是在上面的代码中,当我刚使用cin.tie(NULL)而不是ios_base::sync_with_stdio(false);时,输出与上面“预期行为”部分中提到的相同,而不是“此代码的行为”部分中的输出。

另外,我想知道ios_base::sync_with_stdio(false);cin.tie(NULL)是否相互关联,是否应该一起使用?

我正在寻找对此行为的全面解释。如果您将我的输入样本作为解释,将会更有帮助。

2 个答案:

答案 0 :(得分:1)

问题1

不,这并不意味着您不能同时使用两者,但同时使用两个I / O会导致非常困难的结果预测(两个I / O的交错很难预测)。 / p>

因此,您不应在同一代码中使用它们。在C ++中总是使用C ++ I / O.仅在使用使用C I / O的外部库时才使用该控件。

问题2

tiesync_with_stdio无关。 tie背后的基本思想是确保在输入之前始终打印提示。与cout绑定的cin表示在使用任何cout之前,cin将被刷新(如果需要)。

答案 1 :(得分:0)

你并不真正理解的是与事物同步意味着什么,以及标准输入和标准输出到底是什么。

标准输入和标准输出是您的流程的全局资源。每个过程都有一个标准输入和一个标准输出。 cin表示从标准输入读取的单一方式。但是scanf是另一种阅读它的方式。

标准输入是全球性的。因此,如果一种读取数据的方法读取了某些内容,那么另一种方法会出现并尝试读取内容,第二种尝试读取的内容可能不再存在。这是一个如何发生这种情况的例子。

语句cin >> test;将从标准输入中读取内容。多少钱?好吧,它至少会 来获取单个long类型。但cin完全能够阅读更多内容。通常,cin将根据内部缓冲区大小读取数据。

目前,您的初始输入仅为2 <return>。但是,它不一定是。可能是2 2 2 2 2 10 <return>cin >> test;仍将只读取一个整数。其余的将是未读输入,将由下一个cin读取命令处理。

但是,未读输入是否仍会在全局标准输入中?可能不是; cin可能会读取所有数据并将其推送到内部缓冲区。一旦发生这种情况,标准输入不包含任哦,是的,使用cin将处理2 2 2 2 10输入的其余部分。

但使用scanf不会。为什么?因为它不知道cin的内部缓冲区。 从标准输入读取。 scanf也是如此。它可以有自己未读输入的内部缓冲区,而cin无法读取它。

好吧,除非你同步这两个系统。这正是sync_with_stdio的用途:当它设置为true时(默认为),标准流上的操作将在两个系统之间起作用。 cin可以读取一些字符,而scanf可以读取其他字符,也不会遗漏任何内容。

如果您没有同步它们,那么您不应该尝试在同一个应用程序中使用这两个系统。这样做会导致输入丢失或输出不按正确顺序出现的风险。

cin.tie的行为正是您所链接的答案所说的:它确保在尝试从标准输入读取任何内容之前,将向用户显示写入标准输出的内容。

但是,这仅适用于cincoutscanf不一定参与此类绑定行为(无论同步是否处于活动状态)。因此,如果cout语句在scanf语句开始从标准输入读取之前向标准输出显示任何内容,则未定义。

所以cin.tie不适用于您。