0

この dtor/ctor の順序は正常ですか? もしそうなら、それはなぜですか?

次の単純な関数では

TemporaryObject SimpleFunction();
{
    TemporaryObject obj = MakeObj();

    // ...

    return obj;   // Stepping through at this point we hit TemporaryObject::dtor, MyObject::ctor
}

// At call site
MyObject obj = SimpleFunction();

return ステートメントで、MyObject ctor が呼び出され、次に TemporaryObject dtor が呼び出されることを期待します。(TemporaryObject が最初にコピーされる可能性がありますが、ここでは RVO が一般的です)。

VS2010 (デバッグ ビルド) では、TemporaryObject dtor が最初に呼び出され、次に MyObject コンストラクターが破棄されたオブジェクトで呼び出されます。メモリアドレスを見ると、それが破壊されたオブジェクトが渡されていることが確認されます。疑いがある場合は、デストラクタの副作用は明らかです。

(完全を期すために、MyObject ctor は、TemporaryObject フラグがコピーされたことを示すフラグを設定します。TemporaryObject dtor は、このフラグが設定されていることをアサートします。この場合、「コピー」の前に破壊が発生していることに気付きました)。

4

2 に答える 2

1

回答付きの最小限の完全な例

はい、コピーコンストラクターの前dtor 呼び出されていますが、あなたが考えている理由ではありません。

重要な観察結果はMyObject::dtor、2 回呼び出されていることです (2 つの異なるオブジェクトで、まだクレイジーなコンパイラ バグの結論に飛びつく傾向がある場合に備えて)。したがって、別のコンストラクターを指定した場合でも、コンパイラーがコピー コンストラクターを生成すると聞いたことがあるかもしれませんが、裏でコピーが行われていると推測します。

したがって、以下のコピー コンストラクターのコメントを解除すると、何が起こっているかをより適切に説明する出力が得られ、mActiveフラグも正しく処理されます。

struct TemporaryObject
{
    TemporaryObject()
        :
    mActive(true)
    { 
        std::cout << "TemporaryObject::ctor mActive = " << mActive << ", this = " << (void*)this << std::endl;
    }

   /* TemporaryObject(const TemporaryObject& obj)
        :
    mActive(obj.mActive)
    { 
        obj.mActive = false;
        std::cout << "TemporaryObject::copy_ctor mActive = " << mActive << ", this = " << (void*)this << std::endl;
    }*/

    ~TemporaryObject()
    {
        std::cout << "TemporaryObject::dtor mActive = " << mActive << ", this = " << (void*)this << std::endl;
        // assert(!mActive);
    }

    mutable bool mActive;
};

struct MyObject
{
    MyObject(const TemporaryObject& obj)
    {
        std::cout << "MyObject::ctor obj.mActive = " << obj.mActive << ", &obj = " << (void*)(&obj) << std::endl;
        obj.mActive = false;
    }
};

TemporaryObject SimpleFunction()
{
    TemporaryObject obj;

    // Do stuff

    return obj;
}

int main()
{
    MyObject obj = SimpleFunction();
}

出力:

TemporaryObject::ctor mActive = 1, this = 00EFF4AB
TemporaryObject::dtor mActive = 1, this = 00EFF4AB
MyObject::ctor obj.mActive = 1, &obj = 00EFF4D7
TemporaryObject::dtor mActive = 0, this = 00EFF4D7
于 2012-10-17T06:53:03.223 に答える
0

もちろん、デバッグビルドでそれを確認できます。デバッグバージョンでは、関数からの復帰に最適化がないため、次のルールがあります。

TemporaryObject::ctor    // Copy constructor
TemporaryObject::dtor    // of function local value that reach end of its scope!
MyObject::ctor           // Create MyObject from returned value
TemporaryObject::dtor    // of function return value
于 2012-10-17T07:02:46.970 に答える