c++11 - ios_base::sync_with_stdio(false) 会影响 <fstream> 吗?

标签 c++11 fstream iostream cin cout

众所周知ios_base::sync_with_stdio(false)将有助于 <iostream> 中 cin 和 cout 的性能通过防止同步 b/w C 和 C++ I/O。但是,我很好奇它是否对 <fstream> 有任何影响。 .

我用 GNU C++11 和以下代码(有和没有 ios_base::sync_with_stdio(false) 片段)运行了一些测试:

#include <fstream>
#include <iostream>
#include <chrono>
using namespace std;

ofstream out("out.txt");

int main() {
    auto start = chrono::high_resolution_clock::now();
    long long val = 2;
    long long x=1<<22;
    ios_base::sync_with_stdio(false);
    while (x--) {
        val += x%666;
        out << val << "\n";
    }
    auto end = chrono::high_resolution_clock::now();
    chrono::duration<double> diff = end-start;
    cout<<diff.count()<<" seconds\n";
  return 0;
}

结果如下:
With sync_with_stdio(false): 0.677863 seconds (average 3 trials)
Without sync_with_stdio(false): 0.653789 seconds (average 3 trials)

这是可以预料的吗?与sync_with_stdio(false)的速度几乎相同(如果不是更慢的话)是否有原因?

感谢您的帮助。

最佳答案

sync_with_stdio() 的想法是允许混合输入和输出到标准流对象( stdinstdoutstderr 在 C 和 std::cinstd::coutstd::cerrstd::clog 以及它们的宽字符流C++ 中的对应对象),而无需担心字符被缓冲在所涉及对象的任何缓冲区中。实际上,使用 std::ios_base::sync_with_stdio(true) C++ IOStreams 不能使用自己的缓冲区。在实践中,这通常意味着缓冲 std::streambuf级别完全禁用。但是,如果没有缓冲区,IOStreams 相当昂贵,因为它们处理可能涉及多个虚拟函数调用的单个字符。本质上,您从 std::ios_base::sync_with_stdio(false) 获得的加速允许 C 和 C++ 库使用自己的缓冲区。
另一种方法是在 C 和 C++ 库设施之间共享缓冲区,例如,通过在更强大的 C++ 库设施之上构建 C 库设施(在人们提示这将是一个糟糕的想法之前,让 C I/O较慢:对于标准 C++ 库 IOStreams 的正确实现,这实际上根本不是真的)。我不知道有任何使用它的非实验性实现。使用此设置 std::ios_base::sync_with_stdio(value)根本不会有任何影响。
IOStreams 的典型实现为标准流对象使用与用于文件流的不同的流缓冲区。部分原因可能是标准流对象通常不使用名称打开,而是使用其他标识它们的实体,例如 UNIX 系统上的文件描述符,它需要“后门”接口(interface)才能允许使用 std::filebuf。对于标准流对象。然而,至少早期的 Dinkumware 标准 C++ 库的实现使用了 std::filebuf,例如 MSVC++。对于标准流对象。这个std::filebuf实现只是 FILE* 的包装,即从字面上实现 C++ 标准所说的而不是语义上的实现。一开始这已经是一个糟糕的想法,但通过禁止 std::streambuf 变得更糟。使用 std::ios_base::sync_with_stdio(true) 对所有文件流进行级别缓冲因为该设置也会影响文件流。我不知道这个 [性能] 问题是否已得到解决。 C/C++ 用户日志和/或 P.J.Plauger 的“[draft] 标准 C++ 库”中的旧问题应该显示对此实现的讨论。
tl;博士:根据标准std::ios_base::sync_with_stdio(false)仅更改标准流对象的约束以使其使用更快。它是否具有其他效果取决于 IOStream 实现,并且至少有一个(Dinkumware)有所不同。

关于c++11 - ios_base::sync_with_stdio(false) 会影响 <fstream> 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45491040/

相关文章:

c++ - 在 std::ofstream (c++) 中复制 std::cout

c++ - 如何逐行读取一个文件到一个字符串类型的变量?

C++/NetBeans/CygWin/Windows - <iostream> 中 Unresolved inclusion

c++ - 如何为非类型模板参数使用数字分隔符?

c++ - 如何制作 “own”模板化 map ?

c++ - 存在 std::move 时未使用移动语义

c++ - fork 、管道和文件操作

c++ - 如何确保在关闭 fstream 之前将数据写入磁盘?

c++ - 为什么在调用更复杂的cin和cout时C++ iostream重载失败?

具有重要成员的 C++11 匿名 union