从输入迭代器创建C++ std :: string的性能

CAd*_*ker 9 c++ string stream

我正在做一些非常简单的事情:将整个文本文件从磁盘中抹去std::string.我目前的代码基本上是这样的:

std::ifstream f(filename);
return std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
Run Code Online (Sandbox Code Playgroud)

它不太可能对程序产生任何性能影响,但我仍然很好奇这是否是一种缓慢的方式.

是否存在构造字符串将涉及大量重新分配的风险?在读取之前使用seekg()/ tellg()计算文件大小和reserve()字符串中的那么多空间会更好(也就是说更快)吗?

CTT*_*CTT 31

我对您在stackoverflow上找到的实现(1),我的(2)以及另外两个(3和4)进行了基准测试.

结果(平均100次运行;使用gettimeofday计时,文件是lorem ipsum的40段):

  • readFile1:764
  • readFile2:104
  • readFile3:129
  • readFile4:402

实施:

string readFile1(const string &fileName)
{
    ifstream f(fileName.c_str());
    return string(std::istreambuf_iterator<char>(f),
            std::istreambuf_iterator<char>());
}

string readFile2(const string &fileName)
{
    ifstream ifs(fileName.c_str(), ios::in | ios::binary | ios::ate);

    ifstream::pos_type fileSize = ifs.tellg();
    ifs.seekg(0, ios::beg);

    vector<char> bytes(fileSize);
    ifs.read(&bytes[0], fileSize);

    return string(&bytes[0], fileSize);
}

string readFile3(const string &fileName)
{
    string data;
    ifstream in(fileName.c_str());
    getline(in, data, string::traits_type::to_char_type(
                      string::traits_type::eof()));
    return data;
}

string readFile4(const std::string& filename)
{
    ifstream file(filename.c_str(), ios::in | ios::binary | ios::ate);

    string data;
    data.reserve(file.tellg());
    file.seekg(0, ios::beg);
    data.append(istreambuf_iterator<char>(file.rdbuf()),
                istreambuf_iterator<char>());
    return data;
}
Run Code Online (Sandbox Code Playgroud)

  • 至少在Windows上,readFile1和3不会返回与readFile2和4相同的东西.前者将CRLF转换为LF,而不是后者. (2认同)