Эффективный способ чтения файла в std::vector <char>?

Я бы хотел избежать ненужных копий. Я нацелен на что-то вроде:

std::ifstream testFile( "testfile", "rb" );
std::vector<char> fileContents;
int fileSize = getFileSize( testFile );
fileContents.reserve( fileSize );
testFile.read( &fileContents[0], fileSize );

(что не работает, потому что reserve фактически не вставляет ничего в вектор, поэтому я не могу получить доступ к [0]).

Конечно, std::vector<char> fileContents(fileSize) работает, но есть накладные расходы на инициализацию всех элементов (fileSize может быть довольно большим). То же самое для resize().

Этот вопрос связан не столько с тем, насколько важны эти накладные расходы. Скорее, мне просто интересно узнать, есть ли другой способ.

Ответ 1

Каноническая форма такова:

#include<iterator>
// ...

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

Если вас беспокоит перераспределение, зарезервируйте место в векторе:

#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<char> fileContents;
fileContents.reserve(fileSize);
fileContents.assign(std::istreambuf_iterator<char>(testFile),
                    std::istreambuf_iterator<char>());

Ответ 2

Если вам требуется истинное чтение нулевой копии, то есть для исключения копирования из ядра в пространство пользователя, просто скопируйте файл в память. Напишите свою собственную сопоставленную оболочку файла или используйте ее из boost::interprocess.

Ответ 3

Если я правильно вас понимаю, вы хотите прочитать каждый элемент, но не хотите загружать его все в fileContents, правильно? Я лично не думаю, что это сделало бы ненужные копии, потому что открытые файлы несколько раз снижали бы производительность. В этом случае однократное чтение вектора fileContents является разумным решением.