【问题标题】:Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);ios_base::sync_with_stdio(false) 的意义; cin.tie(NULL);
【发布时间】:2015-09-18 16:08:00
【问题描述】:

包含有什么意义

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

在 C++ 程序中?

在我的测试中,它加快了执行时间,但是我应该担心包含这个的测试用例吗?

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

此外,如果其值已设置为 false,是否允许同时使用 C 和 C++ 命令?

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

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

【问题讨论】:

  • 您实际上将它与 false 一起使用。你的代码是这样说的???

标签: c++ c


【解决方案1】:

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

ios_base::sync_with_stdio(false);

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

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

cin.tie(NULL);

这将cincout 解开。绑定流确保在对另一个流执行每个 I/O 操作之前自动刷新一个流。

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

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

如果cincout 绑定在一起,您可以期望在程序提示用户输入之前刷新输出(即在控制台上可见)。如果您解开流,程序可能会阻止等待用户输入他们的姓名,但“输入姓名”消息尚不可见(因为默认情况下缓冲cout,输出仅在需要时刷新/显示在控制台上或缓冲区已满时)。

因此,如果您将cincout 解开,则必须确保每次在希望在cin 上输入之前手动刷新cout

总之,了解他们每个人的作用,了解后果,然后决定您是否真的想要或需要提高速度的可能副作用。

【讨论】:

  • 当你说“你必须确保每次你想在 cin 上输入内容之前手动刷新 cout”,这可以像附加“...
  • 是的,就是这么简单,但要小心“每一行的结尾”部分。 cout 被缓冲是有原因的,如果你经常刷新它,当你实际上不需要它时,你可能会看到性能下降。
  • @Ionut 是否有与 C 中用于 scanf、printf 的 tie() 功能等效的东西?
  • @iajnr 不,不直接。在 C 中,您可以在 scanf() 之前手动刷新、完全禁用缓冲或切换到行缓冲(应该在换行之后刷新或从 stdin 读取输入时刷新 - 请参阅 linux.die.net/man/3/setlinebuf )。
  • 在 leetcode 中,它显着提高了运行时间,也许这些竞争网站对输入测试做了一些特殊的事情。
【解决方案2】:

这是为了同步来自 C 和 C++ 世界的 IO。如果你同步了,那么你就可以保证所有 IO 的顺序都是你所期望的。一般来说,问题是导致问题的 IO 缓冲,同步让两个世界共享相同的缓冲区。例如cout &lt;&lt; "Hello"; printf("World"); cout &lt;&lt; "Ciao";;如果没有同步,你永远不会知道你会得到HelloCiaoWorldHelloWorldCiao 还是WorldHelloCiao...

tie 让您保证 C++ 世界中的 IO 通道彼此绑定,这意味着例如在输入发生之前每个输出都已刷新(想想cout &lt;&lt; "What's your name ?"; cin &gt;&gt; name; )。

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

【讨论】:

  • 即使没有同步,对cout &lt;&lt; 的不同调用也无法更改顺序,因此CiaoHelloWorld 不适用于您的示例情况。同步严格来说是关于不同的缓冲方法。
  • 我什至不知道这是不是真的,但我因为解释而投了赞成票
【解决方案3】:

这只是使 cin 输入工作更快的常用方法。

简单解释一下:第一行关闭 cin 流和 C 风格 stdio 工具(如 scanf 或 gets)之间的缓冲区同步 - 所以 cin 运行速度更快,但不能与 stdio 工具同时使用。

第二行从 cout 中解开 cin — 默认情况下,每次从 cincout 缓冲区都会刷新/强>。当您反复阅读一些小东西然后多次写一些小东西时,这可能会很慢。所以这条线关闭了这种同步(通过将 cin 绑定到 null 而不是 cout)。

【讨论】:

    【解决方案4】:

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

    cin.tie(NULL) 调用似乎要求在cincout 上的活动之间解耦。我无法解释为什么将它与其他优化一起使用会导致崩溃。如前所述,您提供的链接不好,所以这里没有猜测。

    【讨论】:

      【解决方案5】:

      有很多很棒的答案。我只是想补充一点关于解耦流的小说明。

      cin.tie(NULL);
      

      我在将流与 CodeChef 平台解耦时遇到了问题。当我提交我的代码时,平台响应是“错误答案”,但在绑定流并测试提交之后。它奏效了。

      所以,如果有人想解开流,必须刷新输出流。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-11
        • 2022-01-15
        • 2022-01-15
        • 2013-07-26
        • 1970-01-01
        • 2018-08-20
        • 2016-02-23
        相关资源
        最近更新 更多