2

私が書きたいのは次のようなものです

void foo()
{
    int a = 5;
    ExecuteOnUnwind eou(bind(&cleanupFunc, a));
}

cleanupFunc(a)関数が戻るか、例外がスローされたときに呼び出されるようなものです。私のためにこれを行う機能がすでに利用可能ですか?Google に適切なフレーズを見つけることができませんでしたが、おそらくこれを行う何かがそこにあるようです. そうでない場合は、すぐに以下の解決策をまとめます。奇妙なことに、リリース モードでは動作しないように見えますが、vc10 のデバッグでは動作します。一時的な呼び出しを追加する危険を冒すことなく、両方で一貫して動作するように実装を微調整するにはどうすればよいですか?

編集:修正には、shared_ptr の使用が含まれます。一時的な破損の心配も軽減します。新しいコードは以下です

template <typename T>
struct ExecuteOnUnwindHelper
{   
    ExecuteOnUnwindHelper(const T & _functor) : mFunctor(_functor)
    {
    }

    ~ExecuteOnUnwindHelper()
    {
        mFunctor();
    }

    const T & mFunctor;
};

template <typename T>
boost::shared_ptr<ExecuteOnUnwindHelper<T>> ExecuteOnUnwind(const T & _functor)
{
    return boost::shared_ptr<ExecuteOnUnwindHelper<T>>(new ExecuteOnUnwindHelper<T>(_functor));
}

void cleanupFunc(int a)
{
    wcout << L"cleanup" << endl;
}

void foo()
{
    int a = 5;
    auto eou = ExecuteOnUnwind(boost::bind(&cleanupFunc, 5));
}

int main()
{
    foo();
    return 0;
}
4

2 に答える 2

1

コンパイラは、変数が使用されていないと見なすため、スタックでの変数の作成を何らかの方法で最適化する必要があります。多分それは関数への呼び出しをインライン化し、作成/破棄の部分をスキップします(私はそれが最も可能性が高いと思います)。グローバルセマンティクスは保持されていると考えていますが、例が示すように、実際には安全な最適化ではありません。

明らかに高レベルのセマンティクスを変更するため、これは間違った最適化だと思います。さまざまなコンパイラでテストするのは興味深いことです。家でチャンスがあればVS2012を試してみます。

とにかく、作成/破棄シーケンスを強制的に実行するには、を使用するだけboost::shared_ptrで、オブジェクトの作成と、オブジェクトがスコープ外になったときの破棄(returnステートメントまたは例外スロー)を処理します。

于 2013-03-07T00:43:26.990 に答える
0

最も簡単な解決策は、必要な機能を型のデストラクタに入れることです。あなたの場合、自動/スマートポインターは必要ないはずです。スタックは十分であり、発生している可能性のあるコンパイラの問題を解決できる可能性があります。

class ExecuteOnUnwind
{
public:
~ExecuteOnUnwind()
{
/** Do something */
}

int data;

};

void foo()
{
  ExecuteOnUnwind runOnExit;

/** Functions code here */
runOnExit.data = 5;

}

これが機能しない場合は、影響を受けるコード (つまり、デストラクタ) の最適化を無効にすることができます。

#pragma optimize( "", off )
...
#pragma optimize( "", on )
于 2013-03-07T00:41:38.297 に答える