ios_base :: sync_with_stdio(false);的意义 cin.tie(NULL);


145

包括在内的意义是什么

ios_base::sync_with_stdio(false);
cin.tie(NULL);

在C ++程序中?

在我的测试中,它可以加快执行时间,但是是否有一个我应该担心的测试用例呢?

这两个语句是否总是必须在一起,或者第一个语句是否足够,即忽略cin.tie(NULL)

另外,如果将其值设置为,是否可以同时使用C和C ++命令false

https://www.codechef.com/viewsolution/7316085

上面的代码运行良好,直到我scanf/printf在C ++程序中使用值为true。在这种情况下,它给出了分割错误。这可能是什么解释?


您实际上使用了false。您的代码是这样的???
Suraj Jain

Answers:


231

这两个调用具有不同的含义,与性能无关。它加快了执行时间的事实只是(或可能是)副作用。您应该了解它们各自的功能,不要盲目地将它们包含在每个程序中,因为它们看起来像是一种优化。

ios_base::sync_with_stdio(false);

这将禁用C和C ++标准流之间的同步。默认情况下,所有标准流都是同步的,实际上,这使您可以混合使用C和C ++风格的I / O并获得合理的预期结果。如果禁用同步,则允许C ++流具有其自己的独立缓冲区,这使C和C ++风格的I / O混合成为一种冒险。

还请记住,同步的C ++流是线程安全的(来自不同线程的输出可能会交织,但不会引起数据争用)。

cin.tie(NULL);

这是cin来自的关系cout。绑定的流确保在对另一流进行每个I / O操作之前自动刷新一个流。

默认情况下cin,绑定可cout确保合理的用户交互。例如:

std::cout << "Enter name:";
std::cin >> name;

如果cincout绑在一起,则可以期望在程序提示用户输入之前刷新输出(即,在控制台上可见)。如果您解开流,则该程序可能会阻止等待用户输入其名称,但“ Enter name”消息仍然不可见(由于cout默认情况下已缓冲,因此仅在需要时或在控制台上刷新/显示输出)。缓冲区已满)。

因此,如果您cin从中解开cout,则必须确保cout每次要显示内容时都要进行手动冲洗,然后再输入期望值cin

总之,了解它们各自的作用,了解其后果,然后确定您是否真的想要或需要提高速度的可能副作用。


当您说“必须确保每次要在cin上输入内容之前要显示某些内容时都手动冲洗cout”时,可以简单地将“ ... << std :: flush”或“ ... < <std :: endl”到以“ std :: cout << ...”开头的每一行的末尾,对吗?
艾伦(Alan)

4
是的,就这么简单,但是请注意“每一行的结尾”部分。cout缓冲是有原因的,如果您经常刷新它,当实际上不需要它时,可能会遇到性能下降的情况。
Ionut

@Ionut是否有等效于C中的scanf,printf的tie()功能的东西?
iajnr

1
@iajnr不,不是直接。在C语言中,您可以在之前手动刷新scanf(),完全禁用缓冲或切换到行缓冲(应该在换行符之后或从中读取输入时刷新,stdin请参见linux.die.net/man/3/setlinebuf)。
Ionut

1
在leetcode上,它可以显着改善运行时间,也许这些竞争激烈的网站在输入测试方面做得很特别。
P0W

17

这是为了同步来自C和C ++世界的IO。如果进行同步,则可以保证所有IO的订单都与您期望的一样。通常,问题是导致问题的IO的缓冲,使两个世界同步以共享相同的缓冲区。例如cout << "Hello"; printf("World"); cout << "Ciao";; 没有同步,您将永远不知道是否会获得HelloCiaoWorldor HelloWorldCiaoor or WorldHelloCiao...

tie使您可以保证C ++世界中的IO通道彼此绑定,例如,这意味着每个输出在输入发生之前就已经刷新(请考虑cout << "What's your name ?"; cin >> name;)。

您始终可以混合使用C或C ++ IO,但是如果您想要某些合理的行为,则必须同步两个环境。请注意,通常情况下,如果您使用C语言编程,请使用C stdio,如果您使用C ++语言编程,则不建议将它们混合使用。但是您可能希望将现有的C库混合到C ++代码中,在这种情况下,需要使两者同步。


3
即使没有同步,对的不同调用cout <<也无法更改顺序,因此CiaoHelloWorld在您的示例案例中是不可能的。同步严格是关于不同的缓冲方法。
Mikko Rantalainen

3

使用 ios_base::sync_with_stdio(false);足以解耦CC++流。您可以在下面找到对此的讨论 Langer和Kreft撰写的Standard C ++ IOStreams and Locales中。他们指出,这是如何实现的是实现定义的。

cin.tie(NULL)呼叫似乎要求取消cin和上的活动之间的耦合cout。我无法解释为什么将其与其他优化一起使用会导致崩溃。如前所述,您提供的链接是错误的,因此这里没有猜测。


0

这只是制造cin的普通东西输入工作更快的。

快速说明一下:第一行关闭了cin流和C风格的stdio工具(如scanf或gets)之间的缓冲区同步-因此cin的工作速度更快,但您不能与stdio同时使用它工具。

第二行从cout解除cin绑定 -默认情况下,每次从cin读取内容时,cout缓冲区都会刷新。当您反复读一些小文章然后多次写一些小文章时,这可能会很慢。因此,该行关闭了此同步(通过将cin实际绑定为null而不是cout)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.