2008-09-07 7 views
31

私は数年前にAndrei AlexandrescuとPetru Margineanによって書かれたthis articleに出くわしました。例外安全コードを書くためのScopeGuardというユーティリティクラスを紹介しています。私は、これらのオブジェクトを使ってコーディングした方が本当に良いコードにつながるのか、それともエラー処理を難読化するのかを知りたいのですが、おそらくガードのコールバックがキャッチブロックでよりよく提示されるでしょうか?実際のプロダクションコードでこれを使っている人はいますか?ScopeGuardは本当により良いコードにつながりますか?

+1

C++ 0xの/ C++ 11は今 "shared_ptrの" とのことありません。 –

+0

私はそれがあなたにもっと力を与えるのを見ます。データベースの例はかなり良いです。 shared_ptrを使用すると、ScopedGuardを使用している間は通常は接続を閉じるデストラクタが呼び出されます。例外の場合は実際にロールバックすることができます。 –

答えて

59

これは間違いなくコードを改善します。 RAIIが確立されたイディオムであるため、あなたの暫定的に公式化された主張、それはあいまいであり、コードはcatchブロックからメリットを得ることはC++では真実ではありません。 C++でのリソース処理は、リソース取得によって行われたであり、ガベージコレクションは暗黙のデストラクタ呼び出しによって行われます。

一方、明示的なcatchブロックは、コードフローがはるかに複雑になり、リソース処理を明示的に行わなければならないため、コードを膨らませ微妙なエラーを招きます。

RAII(ScopeGuardを含む)は、C++ではあまり知られていませんが、確かに確立されたベストプラクティスです。

+6

+1現代的なC++テクニックに固執します。また、AlexandrescusがScopeGuardの新しいバージョンを提供していることにも注意してください。http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in -Cははるかに使いやすいです。ミッチは編集する価値がある。 – odinthenerd

1

私はこの特定のテンプレートを使用していませんが、これまでに同様のものを使用しました。はい、さまざまな方法で実装された同様に堅牢なコードと比べると、より明確なコードにつながります。

2

私はしばしば、メモリ使用を守るために、OSから返された解放が必要なものを使用します。例:

DATA_BLOB blobIn, blobOut; 
blobIn.pbData=const_cast<BYTE*>(data); 
blobIn.cbData=length; 

CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &blobOut); 
Guard guardBlob=guardFn(::LocalFree, blobOut.pbData); 
// do stuff with blobOut.pbData 
28

はい。

すべてのC++プログラマーが10分の学習に励むことができるC++コードが1つあれば、それはScopeGuard(現在は無料で利用できるLoki libraryの一部です)です。

私が取り組んでいた小さなWin32 GUIプログラムのために、ScopeGuardの(少し修正された)バージョンを使用しようと決めました。あなたが知っているかもしれないWin32には、さまざまな方法で閉じなければならないさまざまなタイプのリソースがあります(例えば、カーネルハンドルは通常CloseHandle()で閉じ、GDI BeginPaint()EndPaint()などとペアにする必要があります)。 new(例えば、Unicodeとの/からの文字セット変換)のワーキングバッファを割り当てるためにも使用します。

私が驚いたのは、どれくらいでしたか短くでした。基本的に、それは勝利です:あなたのコードは、同時に短くて堅牢になります。将来のコード変更は何もリークできません。彼らはできません。それはどれくらい涼しいですか?

+0

Downvoter:コメントしますか? –

-2

私は、いいえ、そうではありません。ここの答えは、なぜそれが本当にひどいアイデアなのかを示すのに役立ちます。リソースの再利用は、再利用可能なクラスを使用して行う必要があります。スコープガードを使用して達成した唯一のことは、リソースを処理するクラスを作成するのではなく、リソース全体をコードベースで複製することです。

スコープガードは、実際の用途を持っている場合は、リソースの取り扱いはそれらのではない一つです。 RAIIは重複排除され、自動化され、スコープガードは手作業によるコードの重複またはバストであるため、その場合は普通のRAIIに比べて大幅に劣っています。

1

上記の回答には重要なメモが1つもないと思います。他の人が指摘しているように、障害(例外)から独立して割り当てられたリソースを解放するためにScopeGuardを使用することができます。しかし、それはスコープガードを使用したいかもしれない唯一のものではないかもしれません。実際、リンクされた記事の例では、異なる目的のためにScopeGuardを使用しています。要するに、RAIIを適切に使用しているオブジェクトであっても、複数のオブジェクトがある場合には、何らかの形で関連付けられた状態を保つ必要がある場合に便利です。これらのオブジェクトのいずれかの状態の変更によって例外が発生した場合(通常、その状態が変更されなかったことを意味します)、すでに適用されているすべての変更をロールバックする必要があります。これにより、それ自身の問題が発生します(ロールバックが失敗した場合はどうなりますか?)。そのような相関オブジェクトを管理する独自のクラスを展開しようとする可能性がありますが、その数が増えれば乱雑になり、とにかくScopeGuardを内部的に使用することになります。

1

はい。

Dでそれのためにも、特別な構文ということは、C++でとても重要だった:

void somefunction() { 
    writeln("function enter"); 
    // c++ has similar constructs but not in syntax level 
    scope(exit) writeln("function exit"); 

    // do what ever you do, you never miss the function exit output 
} 
関連する問題