7

関数 F() の開始時に作成する単純な C++ オブジェクトがあり、オブジェクトのコンストラクターとデストラクターを使用して、一致する 2 つの関数 (OpDo、OpUndo) が F() の開始時と戻り時に確実に呼び出されるようにします。ただし、F() の本体内で例外がスローされた場合に備えて、操作を元に戻したくありません。これはきれいに行うことができますか?std::uncaught-exceptionについて読んだことがありますが、その使用は推奨されていないようです。

4

3 に答える 3

6

ほとんどの人はstd::uncaught_exception()、例外が保留中かどうかを判断しようとしてきたため、デストラクタがまだない場合はデストラクタから例外をスローできます。それは一般的に、良い考えではないと考えられています。

例外がスローされた場合に操作を元に戻したくない場合は、それでうまくいくはずです。

デストラクタは、オブジェクトが持つリソースを解放する最後のチャンスであることに注意してください。デストラクタが終了すると、オブジェクトは存在しなくなり、オブジェクトが保持していたリソースは永久にリークされるためです。メモリやファイルハンドルなどを割り当てる場合OpDo()は、デストラクタでそれを処理する必要があります。

于 2010-10-25T20:31:37.567 に答える
1

スコープ ガードのイディオムを覆すことができます。例外がスローされないときにデストラクタで何もしない代わりに、それを逆にして、例外がスローされない場合にのみ何かを行います。

class DoUndoRAII{
public:
  DoUndoRAII()
    : noexcept_(false)
  {
    // your stuff here
  }

  ~DoUndoRAII(){
    if(noexcept_){
      // do whatever you need to do
    }
  }

  void no_exception(){
    noexcept_ = true;
  }

private:
  bool noexcept_;
};

void func(){
  DoUndoRAII do_undo;

  // last line
  do_undo.no_exception();
}

例外がスローdo_undo.no_exception()されると、決して呼び出されないため、noexcept_値が true に設定されることはありません。:) 例はIdeone にあります。

于 2011-04-17T08:08:49.510 に答える
0

あなたの F がいくつかのクラス Helper を返すと仮定しましょう:

Helper F()
{
     MyClass doUndoWrapper;
}

フローが正常な場合 - ヘルパーが作成されます。例外が発生すると、ヘルパーのコピーは作成されません。ヘルパーのプライベート リージョン コンストラクターに配置し、F をフレンドとして宣言することで、このセマンティックを使用してみてください。そのため、誰もヘルパーを作成できません。

class Helper
{
private:
    friend Helper F();
    Helper(){ //place there OpDo semantic - first entry 
              // construct this class
    Helper(const Helper& copy){ //this must present to allow stack operations
              // copy constructor will be called at end of `F` to return value
              // so place OpUndo semantic there to mark success without exception
于 2010-10-25T20:40:23.047 に答える