STLの罠 iteratorの動作

C++のSTLライブラリを使い出してから、面倒な処理を書く手間が緩和されるのを体感します(もっとも、ライブラリの汎用性のため見慣れぬ難解な構文になり、返って可読性が悪くなる場合もあります)

今日はVectorコンテナへifstreamからファイル内容を読み込んだときのアクシデントを紹介します。なんと汎用性を持たせたら速度が劇的に遅くなってしまったのでした!

Vector以外のコンテナで影響が出ないようにiteratorを使った例[460KBで11秒]

std::vector vctr;
std::ifstream ifs;

ifs.open(FileName.c_str(), std::ios::in | std::ios::binary);
vctr.assign(std::istreambuf_iterator(ifs), std::istreambuf_iterator());
ifs.close();

Vectorのメモリ空間をファイルサイズ分確保し一気読みした例[460KBで0秒]

ifs.open(FileName.c_str(), std::ios::in | std::ios::binary);
ifs.seekg(0, std::ifstream::end);
vctr.resize(ifs.tellg());
ifs.seekg(0, std::istream::beg);
ifs.read(&vctr[0], vctr.size());
ifs.close();

両者の違いは、前者が1バイトずつファイルアクセス、後者がファイルサイズ分1回だけのアクセスとなります。iteratorの実装により動作は変わるでしょうが、少なくともVC2005のistreambuf_iteratorは効率が悪いです。バイナリ読み込みには使わないほうがいいでしょう。

Vectorは配列のラッパークラスとして、連続したメモリ空間が仕様で保証されています。したがって、後者のような一見危険に見えるコーディングでもOKとなるのでした。