为什么ifstream :: read比使用迭代器快得多?

Ver*_*tas 6 c++ io optimization performance iterator

实际上,有很多方法可以将文件读入字符串.两个常见的是使用ifstream :: read直接读取字符串并使用steambuf_iterators和std :: copy_n:

使用ifstream :: read:

std::ifstream in {"./filename.txt"};
std::string contents;
in.seekg(0, in.end);
contents.resize(in.tellg());
in.seekg(0, in.beg);
in.read(&contents[0], contents.size());
Run Code Online (Sandbox Code Playgroud)

使用std :: copy_n:

std::ifstream in {"./filename.txt"};
std::string contents;
in.seekg(0, in.end);
contents.resize(in.tellg());
in.seekg(0, in.beg);
std::copy_n(std::streambuf_iterator<char>(in), 
            contents.size(), 
            contents.begin();
Run Code Online (Sandbox Code Playgroud)

许多基准测试显示第一种方法比第二种方法快得多(在我的机器中使用g ++ - 4.9它使用-O2和-O3标志的速度大约快10倍)我想知道造成这种差异的原因可能是什么.性能.

Seb*_*edl 2

read是单个 iostream 设置(每个 iostream 操作的一部分)和对操作系统的单个调用,直接读入您提供的缓冲区。

char迭代器的工作原理是重复提取单个operator>>. 由于缓冲区大小的原因,这可能意味着更多的操作系统调用,但更重要的是,它还意味着重复设置和拆除 iostream 哨兵,这可能意味着互斥锁,并且通常意味着一堆其他东西。此外,operator>>是格式化操作,而read是未格式化操作,这是每个操作的额外设置开销。

编辑:疲惫的眼睛看到了 istream_iterator 而不是 istreambuf_iterator。当然istreambuf_iterator不做格式化输入。它在streambuf 上调用sbumpc 或类似的东西。仍然有很多调用,并使用缓冲区,该缓冲区可能小于整个文件。

  • “迭代器的工作原理是使用‘operator&gt;&gt;’重复提取单个字符”——有任何参考吗?事实上,“operator&gt;&gt;”执行格式化输入,而“istreambuf_iterator”执行“未格式化”输入,所以我认为这不太可能。(编辑:根据 [cppreference.com](http://en.cppreference.com/w/cpp/iterator/istreambuf_iterator/operator*) 这个答案是错误的。) (2认同)