Visual Studio 2012で問題が発生しました。最初にSSCCE:
class CacheImpl
{
public:
float* m_cache;
CacheImpl()
{
m_cache=(float*)new float[1];
}
~CacheImpl()
{
delete [] m_cache;
}
};
class Image
{
public:
Image() {}
~Image() {}
};
static const Image g_tmpImg;
class Filter
{
public:
Filter() : m_img(Image())
//Filter() : m_img(g_tmpImg) // <-- This variant works
{
//Empty
}
private:
CacheImpl m_cache;
const Image &m_img;
};
int main()
{
Filter f;
return 0;
}
これを実行すると(デバッグモードでコンパイル)、CacheImplで削除時にCRTアサートが発生し、Filter()のアセンブリリストを確認するか、〜CacheImpl()でブレークポイントを設定すると、〜CacheImpl()がで呼び出されていることがわかります。明らかな理由なしにFilterコンストラクターが終了します(実際、これはVS2010では発生しません)。代わりに、一時オブジェクトに対して〜Image()が呼び出されますが、VS2012では呼び出されません。
VS2012でこれをコンパイルすると、「C4413:'Filter :: m_img':参照メンバーがコンストラクターの終了後に永続化されない一時的なものに初期化されます」という警告が表示されます。これは理解できますが、間違ったオブジェクトが破棄されているため、クラッシュではなく、ぶら下がっている参照を期待しています。コンパイラのバグに遭遇したことがありますか、それともこれを未定義の動作として受け入れ、一時的なものへの参照を初期化するべきではありませんか?コンテキストとして、私の実際のコードでは、このようなコンストラクターを使用してFilterを作成するときに、ぶら下がり参照が使用されることはありません。