3

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を作成するときに、ぶら下がり参照が使用されることはありません。

4

1 に答える 1

0

これはコンパイラのバグであると主張することもできますが、「未定義の動作」は本質的に「何でもあり」を意味し、すぐに破棄されるオブジェクトへの参照を保存することは未定義の動作と見なされます。したがって、これを受け入れて、一時的な参照での初期化を停止する必要があります。

于 2012-10-17T11:33:22.763 に答える