如何优雅高效地将文件读入矢量?

时间:2016-12-14 10:04:25

标签: c++ performance io compiler-optimization idioms

#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

vector<char> f1()
{
    ifstream fin{ "input.txt", ios::binary };
    return
    {
        istreambuf_iterator<char>(fin),
        istreambuf_iterator<char>()
    };
}

vector<char> f2()
{
    vector<char> coll;
    ifstream fin{ "input.txt", ios::binary };
    char buf[1024];
    while (fin.read(buf, sizeof(buf)))
    {
        copy(begin(buf), end(buf),
            back_inserter(coll));
    }

    copy(begin(buf), begin(buf) + fin.gcount(),
        back_inserter(coll));

    return coll;
}

int main()
{
    f1();
    f2();
}

显然,f1()f2()更简洁;所以我更喜欢f1()f2()。但是,我担心f1()效率低于f2()

所以,我的问题是:

主流C ++编译器会优化f1()以使其与f2()一样快吗?

更新

我使用130M的文件在发布模式下测试(Visual Studio 2015 with Clang 3.8):

f1()需要1614 ms,而f2()需要616 ms。

f2()f1()快。

多么悲惨的结果!

2 个答案:

答案 0 :(得分:2)

我已经使用mingw482检查了我的代码。 出于好奇,我添加了一个额外的函数f3,其中包含以下实现:

inline vector<char> f3()
{
    ifstream fin{ filepath, ios::binary };
    fin.seekg (0, fin.end);
    size_t len = fin.tellg();
    fin.seekg (0, fin.beg);

    vector<char> coll(len);
    fin.read(coll.data(), len);
    return coll;
}

我已经使用文件~90M进行了长时间的测试。对于我的平台,结果与您有点不同。

  • f1()~850ms
  • f2()~600ms
  • f3()~70ms

结果计算为连续10次文件读取的平均值。

f3函数占用的时间最短,因为在vector<char> coll(len);它已分配了所有必需的内存,因此不需要进行进一步的重新分配。对于back_inserter,它要求类型具有push_back成员函数。当超过capacity时,对于向量的重新分配。如文档中所述:

  

<强>的push_back

     

这有效地将容器大小增加了一个,这导致了   如果 - 并且仅在以下情况下自动重新分配已分配的存储空间   新的矢量大小超过了当前的矢量容量。

f1f2实施中,虽然两者都使用back_inserter,但后者稍快一些。 f2可能更快,因为它以块的形式读取文件,允许进行一些缓冲。

答案 1 :(得分:-1)

如果小于某GB,您可以一次阅读:

#include "sys/stat.h"
        ....

char* buf;
FILE* fin;
filename="myfile.cgt";
#ifdef WIN32
   struct stat st;
  if (stat(filename, &st) == -1) return 0;
#else
    struct _stat st;
if (_stat(filename, &st) == -1) return 0;
#endif
    fin = fopen(filename, "rb");
    if (!fin) return 0;
    buf = (char*)malloc(st.st_size);
    if (!buf) {fclose(fin); return 0;}
    fread(buf, st.st_size, 1, fin);
    fclose(fin);

无需说你应该使用&#34; new&#34;在C ++而不是malloc()