【问题标题】:How to directly read a huge chunk of memory into std::vector?如何将一大块内存直接读入std::vector?
【发布时间】:2013-01-01 01:33:39
【问题描述】:

我有一个巨大的连续数组x,我来自一个文件fread

如何将此块放入std::vector<>?换句话说,我更喜欢将结果放在 std::vector<> 而不是数组中,但我希望生成的 C++ 代码与将块直接放入数组的普通 C 版本一样高效。

通过四处搜索,我想我可能不得不以某种形式使用placement-new,但我不确定调用顺序和所有权问题。另外,我需要担心对齐问题吗?

我正在使用 T = unsigned 进行测试,但我希望有一个合理的解决方案适用于任何 POD 结构。

using T = unsigned;
FILE* fp = fopen( outfile.c_str(), "r" );
T* x = new T[big_n];
fread( x, sizeof(T), big_n, fp );

// how do I get x into std::vector<T> v
// without calling a gazillion push_backs() or copies ?!?

delete[] x;
fclose( fp );

【问题讨论】:

  • 您有什么理由不直接将文件读取到向量中?
  • @ahenderson - 因为我没有意识到你可以 - Joachim 在下面的回答看起来不错

标签: c++ c++11 placement-new


【解决方案1】:

您使用std::vector constructor 设置向量的大小,并使用std::vector::data 获取指向已分配内存的指针。

继续使用fread

std::vector<T> x(big_n);
fread(x.data(), sizeof(T), big_n, fp);

正如其他人所指出的,如果T 不是POD type 类型,则使用fread 很可能不起作用。然后,您可以使用 C++ 流和std::istreambuf_iterator 将文件读入向量。但是,这样做的缺点是它会遍历文件中的所有项目,如果 big_n 和听起来一样大,那么这可能是一个性能问题。


但是,如果文件真的很大,我更建议使用memory mapping 来读取文件。

【讨论】:

  • 这是一个简单的解决方案,但不如这个普通的 C 版本那么高效,因为它用零值初始化向量。
  • @jrok 如果 T 不是字符类型,您无法使用 fread 可靠地读取它。如果 T 不是 POD,则几乎可以肯定您无法阅读它。
  • 我唯一不喜欢这个解决方案的是通过data方法访问由vector管理的私有内存来打破std::vector封装。
  • @kfmfe04 std::sort 也可以对普通的原始数组进行排序,这就是mmap 返回的内存指针可以看作。
  • @PaperBirdMaster, data() 是一个 public 成员,专门添加到 C++11 中以允许您执行此操作。无论如何,您已经可以在 C++03 中使用 &amp;x[0] 来完成它。 std::vector 的内存布局是其接口的一部分。
【解决方案2】:

这将使用

将文件读入向量
#include <vector>
#include <fstream>
#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<unsigned char> fileContents((std::istreambuf_iterator<unsigned char>(testFile)),
                           std::istreambuf_iterator<unsigned char>());

此答案来自之前的答案:https://stackoverflow.com/a/4761779/942596

【讨论】:

  • +1 是一个有趣的选择——我想这也适用于任何std::vector&lt;POD&gt;?我试试看。
  • @kfmfe04 这是一个很好的问题,我从未测试过。如果可以,请告诉我。
  • 这段代码不起作用,你不能用istreambuf_iterator&lt;unsigned char&gt;basic_istream&lt;char&gt;读取(字符类型不匹配)。此外,在 C++11 中,第二个迭代器可以简单地编写为 {}
  • istreambuf_iterator&lt;unsigned char&gt; + 5 不工作。所以使用这种方法是不可能读取大块文件的
猜你喜欢
  • 2019-05-07
  • 1970-01-01
  • 2014-12-22
  • 2015-01-25
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多