2011-01-21 7 views
34

不要なコピーを避けたいです。ファイルを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

'push_back'で必要な再配置コストを避けたい場合、' resize'を使って必要なバッファをゼロにするコストを避けたい場合は、 'std :: vector'をまったく使用しないでください。 'boost :: scoped_array'かそれに類するものです。 –

答えて

54

正規の形式はこれです:あなたが再配分を心配している場合は、ベクターで、その後の予備スペース

#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>()); 
+0

ベクターが成長している間に再配分はしませんか? (イテレータは減算をサポートしていない可能性があるため、コンストラクタで事前にサイズを決定することはできません。) – Thomas

+0

はい、そうです。それが本当に懸念されるなら、 'std :: copy()'を予約して使用してください。更新しました。 – wilhelmtell

+0

2番目の例では、 'reserve'は' resize'である必要がありますか? –

0

あなたが正しく理解している場合は、各要素を読み込みたいが、すべてをfileContentsにロードしたくないのですが、正しいですか? オープンファイルを複数回実行するとパフォーマンスが低下するため、個人的には不要なコピーが作成されるとは思われません。この場合には、fileContentsベクターに一度読み込むことは妥当な解決策です。

+0

私はこれを投票するつもりはありませんでしたが、それは固定されています。回答を編集すると、私は投票を削除できます。 – ditkin

5

あなたは真のゼロコピー読書をしたい場合、それはに、ありますカーネルからユーザー空間へのコピーを省き、ファイルをメモリにマップするだけです。マップされたファイルラッパーを作成するか、boost::interprocessから1つを使用してください。

関連する問題