C++中文件数据的动态分配

Dynamic allocation of file data in C++

坦率地说,我的作业非常含糊地说,

"If the file exists, the one-argument constructor allocates memory for the number of records contained in the file and copies them into memory."

现在,在考虑这条指令时,我似乎要分配动态内存/之前/复制数据,这在原则上似乎是不可能的。

据我所知,要动态分配内存,您需要运行时定义要保留的块的大小。

鉴于文件大小或 'entries' 的数量未知,怎么可能分配那么多内存?这个概念不会违背动态分配的目的吗?

明智的解决方案,似乎唯一的选择是解析整个文件,确定大小,然后分配适当数量的内存,然后再次读取文件,将数据复制到分配的内存中。

鉴于这一定是任何读取文件数据的程序中的常见操作,我想知道:将文件加载到 RAM 中的正确或最有效的方法是什么?

读取一次确定大小,然后再次复制的想法似乎效率很低。我假设有一种方法可以跳到文件末尾以确定最大长度,这将使过程更快。或者也许使用静态缓冲区并将其以块的形式加载到 RAM?

是否可以读取所有数据,然后使用移动运算符将其移动到动态内存中?或者使用某种链表可能更有效?

最有效的方法是让操作系统将文件映射到内存。在 OS API 中搜索 "mmap" 或 "memory mapping"。

另一种方法是查找文件末尾并获取位置(tellg())。这是文件的大小。在动态内存中分配一个数组或创建一个 std::vector 至少保留此数量的 space.

有些操作系统 API 您可以调用它来获取文件的大小(无需搜索到末尾)。您可以使用此方法,然后动态分配内存或使用 std::vector<char>.

如果文件不适合内存,您将需要制定计划。

如果您需要将整个文件读入内存,您可以使用 istream::read 使用文件长度。

这完全取决于文件格式。一种存储记录的方法是首先写入文件中存储了多少条记录。如果您有两个 phone 号码,您的文件可能如下所示:

2
Jon
555-123
Mary
555-456

在这种情况下,解决方案很简单:

// ...
is >> count;
record_type *record = new record_type[count];
for ( int i = 0; i < count; ++i )
  is >> record[i].name >> record[i].number; // stream checks omitted
// ...

如果文件没有存储记录数(我不会这样做),你就得先数一下,再用上面的解决方法:

// ...
int count = 0;
std::string dummy;
while ( is >> dummy >> dummy )
  ++count;
is.clear();
is.seekg( 0 );
// ...

第二种情况的第二种解决方案是编写一个动态容器(我假设您不允许使用标准容器)并在读取记录时推送它们:

// ...
list_type list;
record_type r;
while ( is >> r.name >> r.number )
  list.push_back( r );
// ...

解决方案按复杂程度排序。我没有编译上面的例子。