2012-03-17 1 views
1

私のコードでは、オブジェクトを動的に割り当てて構築し、ポインタをベクトルにプッシュする必要があります。これらの醜いtry-catchブロックをすべて使用せずに、以下のコードよりもクリーンな方法がありますか?私は非標準ライブラリを使用することはできません。 C++ 11はありません。私は標準C++ 98/03しか持っていません。標準的なC++を使った1つのオブジェクトのきれいな割り振りと構築98/03

void insert() { 
      //...do something... 
      MyType* obj = 0; 
      try { 
       obj = alloc.allocate(1); // yes, even the allocation must be inside one try-catch in my case, since I need to undo something 
       alloc.construct(obj, default_obj); 
       try { 
        v.push_back(obj); 
       } catch (...) { 
        alloc.destroy(obj); 
        throw; 
       } 
      } catch (...) { 
       //..undo something.. 
       if (obj) 
        alloc.deallocate(obj, 1); 
       throw; 
      } 
} 

EDIT: アロケーションはどこか新しい/削除生避けるために、引数として渡されたアロケータです。 vはベクトルです。

+0

なぜnewとdeleteを使用しないのでしょうか?alloc.consturctとalloc.deallocとは何ですか? – 111111

+0

allocは、標準インタフェースを持つアロケータです。生の新規作成と削除を避けるために使用されます。 vはstd :: vectorです – Martin

+1

私はあなたのコンテナを作成しています。その場合、アロケータを扱うカスタムRAIIコンテナを作成し、std :: unique_ptrを参照してください。破壊コードのない単一のtryキャッチ – 111111

答えて

4

明白な解決策は、カスタムRAIIクラスを使用することです:再スローとtry/catchブロックは、(例外タイプを何とか使用されていない場合)2つの管理しやすい点に注意しているが、同じクリーンアップを行うデストラクタに相当します。

  • それは必要な情報を取得する必要があります。すなわち、オブジェクトがキャッチブロックの暗黙のコンテキストを持っていないだろうが、それは一度何かをする必要がないことを知らせるために必要である。すなわちデストラクタは常に、呼び出された
  • に合格しました主操作は成功しました

あなたがきれいにするために必要なことを述べていないので、デストラクタでこれを行う以外に、これをどうやって最善に対処するかについてはコメントできません。アロケータの使用のために、私は実際にコンストラクタの引数とアロケータを引数として独自のコンストラクタに渡すカスタムスマートポインタを作成します(はい、variadicと完璧な転送は使用できません。これはちょっと面倒ですが実行可能です:一度より)。スマートピューターは、実際には正しいアロケータを使用して割り当て解除を処理するために、実際にアロケータをバンドルします。右辺値参照なしでは移動セマンティクスは基本的に正しく実行できないため、スマートポインタは参照カウントを使用します。

一般的に、RAIIを使用すると、例外とは関係なくすべての暗黙の元に戻すことができます:!どんな重要なコードでも、最終的に誰かがやってきて、関数から頻繁に戻ります。 RAIIクラスを作成するにはもう少し前向きな作業かもしれませんが、ビジネスロジックと混ざった技術的な作業から私を劇的に見分けることができました。また、私はRAIIクラスとしての生活を始めましたが、 "リソースの"ロジックにアクセスするために使用された機能をカプセル化したクラスになっています。

関連する問題