使用istream_iterators构造向量

时间:2010-12-12 18:54:13

标签: c++ stl vector iterator

我记得曾经看过一种使用迭代器将整个二进制文件读入矢量的巧妙方法。它看起来像这样:

#include <fstream>
#include <ios>
#include <iostream>
#include <vector>

using namespace std;

int main() {
    ifstream source("myfile.dat", ios::in | ios::binary);
    vector<char> data(istream_iterator(source), ???);
    // do stuff with data
    return 0;
}

我们的想法是通过传递指定整个流的输入迭代器来使用vector的迭代器范围构造函数。问题是我不确定要为最终迭代器传递什么。

如何为文件末尾创建istream_iterator?我完全记错了这个成语吗?

2 个答案:

答案 0 :(得分:24)

您希望std::istreambuf_iterator<>用于原始输入。 std::istream_iterator<>用于格式化输入。至于文件的结尾,请使用流迭代器的默认构造函数。

std::ifstream source("myfile.dat", std::ios::binary);
std::vector<char> data((std::istreambuf_iterator<char>(source)),
                       std::istreambuf_iterator<char>());

已编辑以满足C++'s most vexing parse。谢谢,@ UncleBens。

答案 1 :(得分:6)

在C ++ 11中,可以:

std::ifstream source("myfile.dat", std::ios::binary);
std::vector<char> data(std::istreambuf_iterator<char>(source), {});

这个较短的形式避免了最令人烦恼的解析问题,因为{}参数消除了它作为参数或形式参数的歧义。

@ wilhelmtell的答案也可以通过为data采用大括号初始化程序来更新以避免此问题。仍然在我看来,使用{}更简单,并使初始化形式无关紧要。

修改

或者,如果我们有std::lvalue(可能是std::xvalue而不是std::move):

#include <vector>
#include <fstream>

template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }

int main() {
    using namespace std;

    vector<char> data(
        istreambuf_iterator<char>(lvalue(ifstream("myfile.dat", ios::binary))),
        {}
    );
}