std::vectorをPODの一時バッファとして使う

>>d金魚さん(で良いのかな?名前間違っていたら本当にすいません)
そのTest_VectorSpeedの実装だとvbの前1MBに0が詰まった後,後ろ1MBにdataが詰まると思います.なので,多分1回ぐらいvectorの内部バッファの再配置(とそれに伴うdelete & new)が起きるので,その分のoverheadが出ていると思います.ただ,それを除いても(resizeではなくてreserveを使っても)明示的なfor文とmemcpyでは決定的な差が残ると思います.
ということで,入力がPODの配列の場合,std::vectorが一時バッファとして優秀かどうか,特にmemcpyと比較してどうか?ということを考えてみました.
あらかじめ,2つ断っておきます.
第1に,以下の議論はコンテナとアルゴリズムの実装に依存する部分が大きいです.ですが,恐らく多くのC++の実装で正しいかと思います.(普段,実装依存な議論をする場合,少なくともVC++7.1とGCC3.2.2の実装を見るんですが,今手元にGCC3.2.2がないので,以下の議論はVC++7.1の実装のみを元にしています.)
第2に,今手元に手ごろな実験環境が無いために実験していなくて,以下の議論はあくまで予想になります.実際実験してみたら「やっぱりvectorはPODの配列を入力とする一時バッファとしてはダメポ」な結論になるかも知れません・・・.明日暇があったら実験してみようと思います.
vectorを一時バッファとして使うときに考えられる,以下の3つについてそれぞれ考えてみました.以下ではdataを入力のPOD配列,szを入力のサイズとします.

reserve + push_back

std::vector v;
v.reserve(sz);
for(int i = 0; i < sz; ++i){
  v.push_back(data[i]);
}

通常,for文による明示的なループによる代入とmemcpyとの比較では圧倒的に後者に軍配が上がります.これはmemcpyが実装上の最適化を許されているからです.(確かCに関する本でこのmemcpyに関して論じていたものがあってそれを読んだ覚えがあるのですがタイトルを失念してしまいました.)上のコードではreserveによってあらかじめ内部バッファを伸張しておき,push_backを使用することでvector内部のバッファの再配置(とそれに伴うdelete & new,要素のコピー)を避けています.が,これは結局のところ1要素ずつの明示的な代入に過ぎず,memcpyと比較して圧倒的に遅いであろうことは想像に難くないです.

resize + memcpy

std::vector v;
v.resize(sz);
memcpy(&v[0], data, data + sz);

まず最初に1点.&v[0]のようにvectorの内部バッファを連続した配列とみなした上でCAPIに突っ込むのは標準で保証された安全な操作です.(ISO/IEC 14882-2003 23.2.4 -1-が論拠になります.後,「Effective STL」も参考になります.)
上のコードはそこそこ速いと思われます.が,そこそこ速いのは恐らくvectorvalue_typeが(unsigned) charの場合だけです.他のPOD,例えばint等ではresizeしたときに明示的なfor文による初期化が行われるため,このやり方でも依然memcpyと比較して圧倒的に遅いという主張は恐らく正しいかと思います.
ちなみに,value_typeがcharの時だけそこそこ速いだろうと予想する理由ですが,resizeがfill_nで実装されていて,そのfill_nが(unsigned) char*に対してのみ特別にdispatchされていてmemsetで実装されているところに由来します.

iterator範囲によるコンストラクタ

std::vector v(data, data + sz);

PODに対して(というか,PODに限らずポインタとサイズが与えられたときにvectorを初期化する手段として)最善となるコードです.上のコードによって具体的に何がなされるかはおおよそ以下のとおりです.

  1. 引数のiteratorの差(distance)から確保するべきbufferのサイズを計算し,必要なサイズのバッファを確保する(引数がポインタ,即ちrandom_access_iteratorなのでこれが定数複雑性で可能)
  2. 確保したバッファに対してstd::uninitialized_copyを呼ぶ.uninitialized_copyは名前のとおり確保はしているがオブジェクトの構築を行っていないメモリに対して値をcopyするアルゴリズムで,PODに対してはmemmove,non-PODに対しては明示的なfor文による配置構文new(placement new)で実装される.

従って,value_typeがPODなら本質的にはnew + memmoveな実装になるため,これだとmemcpyと比較してもある程度耐えうる速度が出る(というか,多分フリーストア確保の速度が圧倒的に遅いはずなので,memcpyとの差が目立たなくなる)と予想されますがどうでしょうか?
ちなみに,すでにvectorのオブジェクトがある場合に,ポインタの範囲でこれを再初期化するインタフェースとしてiterator範囲によるassignがあります.

v.assign(data, data + sz);