阅读std::vector
这是一个好主意,还是有一些问题:
using namespace std;
ifstream file("blah.dat", ios::binary);
vector<T> v(N);
file.read(static_cast<char*>(v.data()), N * sizeof(T));
vector
标准是否允许我这样做来填充向量?为简单起见,我们假设T是普通的旧数据类型。
答案 0 :(得分:2)
如果T
可以轻易复制,那么这里没有未定义的行为,POD肯定是。 vector<T>::data
保证返回指向vector<T>::size
T
的连续数组的指针,并且保证平凡可复制类型T
的对象表示是连续的序列sizeof(T)
个字节(可能包括内部填充)。
如果存储到该空间的字节不是有效的T
对象表示,则在访问它们时可能会出现未定义的行为。究竟哪个字节序列构成有效的T
对象表示是一个灰色区域;至少你应该能够将一个简单可复制类型的对象的底层字节可移植地写入文件,并成功地将它们读回到相同类型的对象的底层字节中。
对于偏执狂的缘故,我可能会说:
static_assert(std::is_trivially_copyable<T>(),
"NO NO NO - T MUST BE TRIVIALLY COPYABLE!");
在file.read
之前进行未来验证。
答案 1 :(得分:1)
看起来你会从内存映射文件中受益。 Boost提供了两种实现方式,因此您不必直接使用mmap()
。
#include <boost/iostreams/device/mapped_file.hpp>
boost::iostreams::mapped_file_source file("blah.dat");
std::size_t size = file.size() / sizeof(T);
const T * ptr = reinterpret_cast<const T*>(file.data());
for (std::size_t i=0; i<size; ++i)
std::cout << ptr[i] << std::endl;
您也可以使用boost.interprocess,但它需要更多代码才能实现相同的功能。
主要优点是您没有分配任何内存来访问该文件,它将在访问数据时按需加载。数据本身将存在于缓存/缓冲页面中,因此它不会占用任何内存(如果系统需要其他内存,则会丢弃它们。)
答案 2 :(得分:0)
你不应该这样做,事实上你应该做的事情(因为原来的C ++)是这个
std::ifstream file("foo.txt");
file >> std::noskipws; // use this line so that whitespace won't be skipped
std::vector<char> buffer(std::istream_iterator<char>(file),
std::istream_iterator<char>());
你不应该按自己的方式去做的原因是因为一个对象生活在一个文件中是没有意义的(至少在C ++中)。文件只包含字符,然后由operator>>
格式化以创建对象。该标准允许编译器对一个对象做一些非常奇怪的事情(特别是当启用了RTTI时),这使得将一个对象“保存”到一个文件是没用的。你最好只为它创建自己的序列化格式。