std :: unique_ptrs(特にMSFT VS 10.0の実装)に問題があります。それらのstd::listを作成するとき、基礎となるオブジェクトだけのstd :: listを作成するときの2倍のメモリを使用します(注:これは大きなオブジェクトです-〜200バイトなので、単なる周りにある追加の参照カウンター)。
言い換えれば、私が実行した場合:
std::list<MyObj> X;
X.resize( 1000, MyObj());
私のアプリケーションは、実行時の半分のメモリを必要とします。
std::list<std::unique_ptr<MyObj>> X;
for ( int i=0; i<1000; i++ ) X.push_back(std::unique_ptr<MyObj>(new MyObj()));
MSFTの実装を確認しましたが、明らかなものは何もありません。誰かがこれに遭遇し、何かアイデアがありますか?
編集: わかりました、もう少し明確/具体的にします。これは明らかにWindowsのメモリ使用量の問題であり、明らかに何かが欠けています。私は今、次のことを試しました:
std::list
100000MyObjのを作成しますstd::list
100000MyObj*のを作成しますstd::list
100000int*のを作成しますstd::list
50000int*のを作成します
いずれの場合も、リストの各追加メンバーは、ポインターであろうとなかろうと、アプリケーションを4400(!)バイト膨らませています。これはリリースの64ビットビルドであり、デバッグ情報は含まれていません([リンカー]>[デバッグ]>[デバッグ情報の生成]が[いいえ]に設定されています)。
明らかに、これをもう少し調査して、より小さなテストケースに絞り込む必要があります。
興味のある方のために、ProcessExplorerを使用してアプリケーションのサイズを決定しています。
それは完全にヒープの断片化であったことが判明しました。なんてばかげている。8バイトのオブジェクトあたり4400バイト!事前割り当てに切り替えたところ、問題は完全に解消されました。オブジェクトごとの割り当てに依存することの非効率性に慣れていますが、これはばかげたことです。
以下のMyObjの実装:
class MyObj
{
public:
MyObj() { memset(this,0,sizeof(MyObj)); }
double m_1;
double m_2;
double m_3;
double m_4;
double m_5;
double m_6;
double m_7;
double m_8;
double m_9;
double m_10;
double m_11;
double m_12;
double m_13;
double m_14;
double m_15;
double m_16;
double m_17;
double m_18;
double m_19;
double m_20;
double m_21;
double m_22;
double m_23;
CUnit* m_UnitPtr;
CUnitPos* m_UnitPosPtr;
};